を使用ExecutorService
してバックグラウンドでタスクを実行し、返された のメソッドを使用しFuture
て結果を待つことができます。例えば:
class Main {
private static final ExecutorService es = Executors.newCachedThreadPool();
public static void main(final String... args) throws Throwable {
List<Future<Integer>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(asyncSum(i, i*i));
}
// here, in the main thread, you can do whatever you want
// while the calculations are performed in background threads
// ...
// after the main thread finishes what it was doing, it
// can process the futures
for (final Future<Integer> result : results) {
System.out.println(result.get());
}
}
// this method launches a calculation on a worker thread and immediately
// returns a Future, which is a reference to the result of the calculation
// once it is completed
private static Future<Integer> asyncSum(final int a, final int b) {
return es.submit(new Callable<Integer>() {
@Override public Integer call() throws Exception {
return a + b;
}
});
}
}
上記の例では、メイン スレッドは最初の計算が完了するまでブロックし、それを出力します。次に、2 番目の計算が完了するまでブロックし、それを出力します。
結果が利用可能になったときに(不特定の順序で)結果を出力したい場合は、 を使用できます。結果のリストを取得して反復処理する代わりに、メソッドCompletionService
を介して CompletionService 自体から先物を取得します。.take()
、計算が終了するまでブロックするか.poll()
、終了した計算がある場合は Future を返し、計算が終了していない場合は null を返します。このようにして、メインスレッドはブロックされません。
次の例では、CompletionService
. これは、決してブロックせず、バックグラウンド スレッドを使用して計算を行い、結果が利用可能になったときに処理するメイン スレッドを示しています。
class Main {
public static void main(String[] args) throws Throwable {
final ExecutorService es = Executors.newCachedThreadPool();
final CompletionService<Integer> cs = new ExecutorCompletionService<>(es);
submitSomeCalculations(cs);
while (true) {
doMainThreadWork();
processFinishedCalculations(cs);
}
}
private static void submitSomeCalculations(final CompletionService<Integer> cs) {
for (int i = 0; i < 10; i++) {
submitAsyncSum(cs, i, i * i);
}
}
private static void submitAsyncSum(final CompletionService<Integer> cs, final int a, final int b) {
cs.submit(new Callable<Integer>() {
@Override public Integer call() throws Exception {
Thread.sleep(100 + (long) (Math.random() * 900));
return a + b;
}
});
}
private static void processFinishedCalculations(final CompletionService<Integer> cs) throws ExecutionException, InterruptedException {
while (true) {
final Future<Integer> result = cs.poll();
if (result == null) {
System.out.println("> no finished results...");
break;
} else {
System.out.println("> result available: " + result.get());
}
}
}
static void doMainThreadWork() {
System.out.println("work from main thread...");
}
}