2013-05-14 8 views
7

私はJavaでExecutorServiceを使用して複数のスレッドを実行するアプリケーションを作成しています。ExecutorServiceで完了したタスクを追跡する

複数のタスク(一度に何千も)をCallableとしてExecutorに提出したい場合は、その結果を取得します。私がこれに近づく方法は、submit()関数を呼び出すたびに、私はArrayListに格納するFutureを取得します。後で、タスクを完了したかどうかを調べるために、future.get()関数をタイムアウトで呼び出すことで、リストを繰り返し処理するスレッドにListを渡します。これは適切なアプローチですか、あまりにも非効率ですか?

EDIT ---詳細--- 別の問題は、各Callableが異なる処理時間を要することです。したがって、リストから最初の要素を取り出し、その上でget()を呼び出すと、ブロックされ、他の要素の結果が利用可能になり、プログラムは認識しません。そのため、私はタイムアウトを繰り返す必要があります。事前に

おかげ

+0

を参照してください。私はあなたがグアバライブラリにListenableFutureユーティリティを検討することをお勧めします。https://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained – Enwired

答えて

1

答えが利用可能になるまで、Future.getの呼び出しはブロックされます。したがって、配列リストを反復処理するために別のスレッドは必要ありません。

ここhttps://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6

+0

は理解していました。しかし、私はExecutorServiceに数千のタスクをバーストで提出します。だから将来の参考のためにFuturesをどこかに保管する必要がある。私が最初のCallableでブロックされている間、別のものが完了していて、私は知らないでしょう。何か案は? –

+0

それらをリストに保存するのは問題ありません。ブロックされたものが完成するとすぐに終了したものに行きます。 – Woody

+0

それらをリストに保存するのは問題ありません。ブロックされたものが完成するとすぐに終了したものに行きます。一回の完了を完了した瞬間に通知する必要がある場合などUIを更新するには、一般にポーリングではなく通知メカニズムを使用する必要があります。 Future.getはあまりにも一般的な仕組みだと思う。 – Woody

6

は、これは正しいアプローチであるか、あまりにも非効率的ですか?

これは正しいアプローチではありません。タスクの完了を確認するために、ArrayListを不必要に繰り返しています。

これは非常に簡単です。ちょうど:CompletionServiceを使用してください。既存のエグゼキュータを簡単にラップすることができます。 JavaDocsより:

プロデューサは実行するタスクを送信します。消費者は完了したタスク を受け取り、完了した順に結果を処理します。

実質的にCompletionServiceは、take()を呼び出すだけで結果を得る方法を提供します。これはブロッキング関数であり、呼び出し元は結果が利用可能になるまでブロックします。


関連する問題