執行器、執行器服務、執行器 - 1

“嗨,阿米戈!”

“沒有什麼東西在最初創建時是完美的。線程也是如此。隨著時間的推移,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這個類,它有什麼方法?”

“這是最有趣的:”

方法 描述
boolean cancel(boolean mayInterrupt);
停止任務。
boolean isCancelled();
如果任務已停止,則返回 true。
boolean isDone();
如果任務完成執行則返回 true。
V get() throws InterruptedException, ExecutionException;
返回調用方法的結果,如果發生異常則拋出異常。

“酷!這樣你也可以停止任務了。”

“不要過分依賴它——不是每個線程都能停止。但如果任務仍在隊列中,那麼它就可以正常工作。”

“我喜歡這種方法。它比自己創建線程然後嘗試從中提取結果要方便得多。”

“太好了。今天我們就到這裡結束。”