ExecutorCompletionService
、、Executor
およびCallable
.を使用します。
関数Callable
を呼び出すa から始めます。int
public class MyCallable implements Callable<Integer> {
private final int i;
public MyCallable(int i) {
this.i = i;
}
public Integer call() {
return Integer.valueOf(myFunction(i));
}
}
を作成しますExecutor
。
private final Executor executor = Executors.newFixedThreadPool(10);
10
一度に実行するスレッドの最大数です。
次に、それをラップして、ExecutorCompletionService
ジョブを送信します。
CompletionService<Integer> compService = new ExecutionCompletionService<Integer>(executor);
// Make sure to track the number of jobs you submit
int jobCount;
for (int i = 0; i < n; i++) {
compService.submit(new MyCallable(i));
jobCount++;
}
// Get the results
int a = 0;
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
}
ExecutorCompletionService
完了したタスクをキューから引き出すことができます。これは、スレッドの結合とは少し異なります。全体的な結果は同じですが、スレッドの完了時に UI を更新する場合、結合を使用してスレッドがどの順序で完了するかわかりません。最後のfor
ループは次のようになります。
for (int i = 0; i < jobCount; i++) {
a += compService.take().get().intValue();
updateUi(a);
}
これにより、タスクが完了すると UI が更新されます。スレッドが完了する順序ではなく、結合を呼び出した順序で結果が得られるため、 a を使用してThread.join
も必ずしもこれが行われるわけではありません。
エグゼキューターを使用することで、同時に実行するジョブの数を制限できるため、誤ってシステムをスレッド爆撃しないようにすることもできます。