0

たとえば、15個の呼び出し可能なタスクを作成し、それらを送信しています。

List<Future<MyResult>> futures = new ArrayList<Future<MyResult>>();
List<MyResult> myResults = new ArrayList<MyResult>();

for(int i = 1; i <= 15; i++){
    Callable<MyResult> task = new MyProcessor(//parameters);
    Future<MyResult> future = executorService.submit(task);
    futures.add(future);//used to iterate over to call get() to collect results in next for loop
}

次に、15個のMyResultオブジェクトを収集しています。

for(Future<MyResult> future : futures){
  try {
    MyResult myResult = future.get();
    processorResults.add(myResult);
    } catch (InterruptedException e) {
      //...
    } catch (ExecutionException e) {
      //...
    }
}

問題は次のとおりです。get()メソッドから15個すべてのMyResultオブジェクトを取得する代わりに、15個未満のオブジェクトを取得することがあります。時には12、時には10、時にはさらに少なく、時にはすべて15。

メソッドはブロッキング呼び出しであり、15個のスレッドすべてがそれぞれの結果を返すのを待つという印象を受けましたがget()、そのうちのいくつかを見逃して先に進むようです。私が間違っているのは何ですか?結果を収集していない/結果を正しく待っていませんか?これは、MyProcessorタスクのいずれかからエラーがスローされたときに発生しますか?

4

1 に答える 1

6

それはあなたの仕事のいくつかが例外を投げたことを意味するかもしれません。コードから見分けるのは難しいですが、ExecutionExceptionそれをキャッチして無視する以外のことをする必要があります。

Future.get()送信したがメソッドからをスローするとスローExecutionExceptionします。メソッドが。で正常に返される場合にのみ、を返します。次の手順を実行すると、スローされた例外を取得できます。CallableRuntimeExceptioncall()MyResultreturn

} catch (ExecutionException e) {
    // account for the throw here, the original exception is in e.getCause()
    // log it, count it, or ...
    logger.error("Job threw exception: " + e.getCause());
}

get()メソッドはブロッキング呼び出しであり、15個のスレッドすべてがそれぞれの結果を返すのを待つという印象を受けました。

正解です。呼び出すfuture.get()と、ジョブが終了するまでブロックされます-例外をスローするか、戻るかによって。進行中のスレッドget()が中断された場合、get()スローは、InterruptedException単に無視されるのではなく、キャッチされる必要があります。

于 2012-07-30T17:42:10.020 に答える