“嗨,阿米戈!”
“沒有什麼東西在最初創建時是完美的。線程也是如此。隨著時間的推移,Java 的創建者開始確信 Runnable 接口的缺點。它不支持拋出異常,也無法找出執行任務的結果……”
“Runnable 接口更適合大型獨立任務,而不是您想要一次運行十幾個,然後收集它們的結果的小型子任務。”
“這就是發明Callable接口的原因。它比Runnable和Thread更適合併行執行小任務,部分原因是它是一個通用接口。”
“這是接口的典型實現:”
例子
class ReverseString implements Callable<String>
{
String str;
ReverseString(String str)
{
this.str = str;
}
public String call() throws Exception
{
StringBuilder builder = new StringBuilder(str);
builder.reverse();
return builder.toString();
}
}
“與Runnable不同,這裡我們需要重寫 call 方法,該方法返回由類型參數指定的類型的結果。這種方法比 Runnable 接口的 run 方法返回 void 更方便。有時開發人員不得不想出獲得線程結果的各種解決方法。”
“我懂了。”
“現在看看Callable如何與 ThreadPoolExecutor 一起工作:
“首先,ThreadPoolExecutor類的提交方法返回一個參數化的 Future 對象。您可以使用該對象來確定任務是否完成並獲取結果。”
“這是它的工作原理:”
例子
// 1. Create a ThreadPoolExecutor
ExecutorService service = Executors.newFixedThreadPool(5);
// 2. Add a task to it
Future<String> task = service.submit(new ReverseString("Amigo"));
// 3. Wait until the task is done
while(!task.isDone())
{
Thread.sleep(1);
}
// 4. Try to get the result
//We will get either the result, or an exception if one occurred while the task was being executed
try
{
System.out.println("Full string : " + task.get());
}
catch (Exception ie)
{
ie.printStackTrace(System.err);
}
// 5. Stop the ThreadPool.
service.shutdown();
“扯遠了!我特別喜歡Future這個類,它有什麼方法?”
“這是最有趣的:”
方法 | 描述 |
---|---|
|
停止任務。 |
|
如果任務已停止,則返回 true。 |
|
如果任務完成執行則返回 true。 |
|
返回調用方法的結果,如果發生異常則拋出異常。 |
“酷!這樣你也可以停止任務了。”
“不要過分依賴它——不是每個線程都能停止。但如果任務仍在隊列中,那麼它就可以正常工作。”
“我喜歡這種方法。它比自己創建線程然後嘗試從中提取結果要方便得多。”
“太好了。今天我們就到這裡結束。”
GO TO FULL VERSION