64

使用できません。待機中shutdown()awaitTermination()ThreadPoolExecutor に新しいタスクが追加される可能性があるためです。

そのため、ThreadPoolExecutor がキューを空にし、その時点より前に新しいタスクが追加されるのを止めることなく、すべてのタスクを終了するまで待機する方法を探しています。

違いがある場合、これは Android 用です。

ありがとう

更新:これを再訪してから数週間後、この場合、変更された CountDownLatch の方がうまく機能することがわかりました。私が尋ねたことにもっと当てはまるので、私は答えをマークしたままにします。

4

7 に答える 7

74

特定のタスクまたは特定のタスクのバッチがいつ完了するかを知りたい場合は、 を使用できますExecutorService.submit(Runnable)。このメソッドを呼び出すと、Futureオブジェクトが返されます。このオブジェクトはCollection、メイン スレッドがそれぞれの呼び出しFuture.get()を反復処理する に配置できます。ExecutorServiceこれにより、すべてのRunnableタスクが処理されるまで、メイン スレッドの実行が停止します。

Collection<Future<?>> futures = new LinkedList<Future<?>>();
futures.add(executorService.submit(myRunnable));
for (Future<?> future:futures) {
    future.get();
}
于 2010-10-14T02:00:37.020 に答える
8

My Scenario は、Web サイトから情報を取得して処理する Web クローラーです。一度に多くのページをロードできるため、ThreadPoolExecutor を使用してプロセスを高速化します。クローラーは各ページのハイパーリンクをたどるため、既存のタスクに新しいタスクが作成されます。問題は同じです。メイン スレッドは、すべてのタスクがいつ完了したかを認識せず、結果の処理を開始できます。私はこれを決定するために簡単な方法を使用します。あまりエレガントではありませんが、私の場合はうまくいきます:

while (executor.getTaskCount()!=executor.getCompletedTaskCount()){
    System.err.println("count="+executor.getTaskCount()+","+executor.getCompletedTaskCount());
    Thread.sleep(5000);
}
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);
于 2012-02-23T01:42:41.780 に答える
6

タスクのバッチを管理するためのCompletionServiceを探しているかもしれません。この回答も参照してください。

于 2010-10-14T02:04:17.253 に答える
3

(これは、Thilo の以前の削除された回答を私自身の調整で再現する試みです。)

暗黙の無限条件があるため、質問を明確にする必要があると思います...ある時点でエグゼキュータをシャットダウンすることを決定する必要があり、その時点でそれ以上のタスクを受け入れなくなります。あなたの質問は、自分のアプリケーション コードでしか知ることができない、それ以上のタスクが送信されないことがわかるまで待ちたいということを暗示しているようです。

次の回答により、(何らかの理由で) 新しい TPE にスムーズに移行し、現在送信されているすべてのタスクを完了し、新しい TPE への新しいタスクを拒否することができなくなります。それはあなたの質問に答えるかもしれません。@Thiloの可能性もあります。

使用中の目に見えるTPEをどこかに定義していると仮定します。

AtomicReference<ThreadPoolExecutor> publiclyAvailableTPE = ...;

その後、TPE スワップ ルーチンをそのように記述できます。同期メソッドを使用して記述することもできますが、こちらの方が簡単だと思います。

void rotateTPE()
{
   ThreadPoolExecutor newTPE = createNewTPE();
   // atomic swap with publicly-visible TPE
   ThreadPoolExecutor oldTPE = publiclyAvailableTPE.getAndSet(newTPE);
   oldTPE.shutdown();

   // and if you want this method to block awaiting completion of old tasks in  
   // the previously visible TPE
   oldTPE.awaitTermination();
} 

あるいは、本当に冗談でスレッドプールを強制終了したくない場合は、サブミッター側が拒否されたタスクに対処する必要があるnullため、新しい TPE を使用できます。

void killTPE()
{
   ThreadPoolExecutor oldTPE = publiclyAvailableTPE.getAndSet(null);
   oldTPE.shutdown();

   // and if you want this method to block awaiting completion of old tasks in  
   // the previously visible TPE
   oldTPE.awaitTermination();
} 

これはアップストリームの問題を引き起こす可能性があり、呼び出し元はnull.

また、すべての新しい実行を単純に拒否するダミーの TPE と交換することもできますが、これshutdown()は TPE を呼び出した場合と同じです。

于 2010-10-14T12:45:19.333 に答える
1

を使用したくない場合はshutdown、以下のアプローチに従ってください。

  1. 送信からすべてのFutureタスクを繰り返し、オブジェクトの呼び出しをExecutorServiceブロックしてステータスを確認しますget()FutureTim Bender

  2. 次のいずれかを使用します

    1. での invokeAllの使用ExecutorService
    2. CountDownLatch の使用
    3. ForkJoinPoolまたはnewWorkStealingPoolの使用Executors(Java 8 以降)

invokeAll()on executor service も同じ目的を達成しますCountDownLatch

関連する SE の質問:

多数のスレッドが完了するのを待つ方法は?

于 2016-04-19T12:21:19.400 に答える
0

RunnerクラスでwaitTillDone()を呼び出すことができます。

Runner runner = Runner.runner(10);

runner.runIn(2, SECONDS, runnable);
runner.run(runnable); // each of this runnables could submit more tasks

runner.waitTillDone(); // blocks until all tasks are finished (or failed)

// and now reuse it

runner.runIn(500, MILLISECONDS, callable);

runner.waitTillDone();
runner.shutdown();

それを使用するには、この gradle/maven 依存関係をプロジェクトに追加します。'com.github.matejtymes:javafixes:1.0'

詳細については、こちらをご覧ください: https://github.com/MatejTymes/JavaFixesまたはこちら: http://matejtymes.blogspot.com/2016/04/executor-that-notifies-you-when-task.html

于 2016-04-29T01:32:48.337 に答える
0

以下に示すように、キューサイズとアクティブタスク数を使用してみてください

 while (executor.getThreadPoolExecutor().getActiveCount() != 0 || !executor.getThreadPoolExecutor().getQueue().isEmpty()){
                     try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }
于 2019-08-16T14:28:44.757 に答える