2012年11月8日 星期四

從 Thread 接受回傳值:Callable

一般使用 Thread 都會使用 Runnable,但是 Runnable 預設要實作的 run() 回傳值是 void,並且 run 也無法回應 Exception
當外邊有 Thread 需要等其他 Thread 執行完畢後的結果時,常常只能另外寫一個 get() 函式去判斷並取值。
不過在 Java 1.5.0 版開始,額外增加了 Callable,可以允許 Thread 回傳值了。

基本的範例可以直接參考 [1] 的範例~
簡單來說,在宣告 Callable 時,就要先宣告回傳值,然後用 Future 去綁對應的 Callable
最後把 Future 餵給 Thread 去執行~就可以透過 Future.get() 函式取得 Callable 執行完畢後的回傳值。

因為我的狀況是要同時執行很多個 Thread,然後收集每個 Thread 運算的結果回來
因此程式碼稍微複雜一點,會宣告一個 ArrayList 存放所有的 Future 實體
之後又會宣告另一個 ArrayList,存放每個 Future 回傳的值。
參考範例如下:
int numOfThreads = 10;

ArrayList<FutureTask<Object>> list = new ArrayList<FutureTask<Object>>(numOfThreads);
for(int i=0 ; i<numOfThreads ; i++) {
  int tempInterval = (i == bucketLength-1) ? -1 : interval;

  Callable<Object> thread = new CallableClass();
  FutureTask<Object> task = new FutureTask<Object>(thread);
  // Start thread.
  Thread t = new Thread(task);
  t.start();
  // Add to list.
  list.add(task);
}
    
ArrayList<Object> allItem = new ArrayList<Object>();

for(int i=0 ; i<numOfThreads ; i++) {
  FutureTask<Object> task = list.get(i);
  try {
    allItem.add(task.get());
  } catch (Exception e) {
    e.printStackTrace();
  }
}

需要注意的是,呼叫 Future.get() 時,程序會一直等到當前的 Callable 執行完畢並回傳資料
因此這個寫法是照順序依序等第一個、第二個、...、第 numOfThreads 個 Callable 回傳資料。

參考資料:
1、Java Gossip: Callable 與 Future

沒有留言: