33

私の質問:で一連のスレッド化されたオブジェクトを実行し、ThreadPoolExecutorそれらがすべて終了するのを待ってから次に進むにはどうすればよいですか?

ThreadPoolExecutor は初めてです。したがって、このコードは、それがどのように機能するかを学習するためのテストです。別のBlockingQueueを呼び出さずにキューを開始する方法を理解していないため、現在、 をオブジェクトで満たすことさえできません。とにかく、今電話しただけですが、まだ何かが足りないと思います。どんなヒントも素晴らしいでしょう!ありがとう。execute()RunnableObjectawaitTermination()

public void testThreadPoolExecutor() throws InterruptedException {
  int limit = 20;
  BlockingQueue q = new ArrayBlockingQueue(limit);
  ThreadPoolExecutor ex = new ThreadPoolExecutor(limit, limit, 20, TimeUnit.SECONDS, q);
  for (int i = 0; i < limit; i++) {
    ex.execute(new RunnableObject(i + 1));
  }
  ex.awaitTermination(2, TimeUnit.SECONDS);
  System.out.println("finished");
}

RunnableObject クラス:

package playground;

public class RunnableObject implements Runnable {

  private final int id;

  public RunnableObject(int id) {
    this.id = id;
  }

  @Override
  public void run() {
    System.out.println("ID: " + id + " started");
    try {
      Thread.sleep(2354);
    } catch (InterruptedException ignore) {
    }
    System.out.println("ID: " + id + " ended");
  }
}
4

6 に答える 6

54

ループする必要がありますawaitTermination

ExecutorService threads;
// ...
// Tell threads to finish off.
threads.shutdown();
// Wait for everything to finish.
while (!threads.awaitTermination(10, TimeUnit.SECONDS)) {
  log.info("Awaiting completion of threads.");
}
于 2012-06-07T16:15:19.567 に答える
8

shutdownあなたの問題は、すべてのジョブをプールに送信した後、呼び出しを行っていないようです。shutdown()あなたの意志がなければ、awaitTermination常にfalseを返します。

ThreadPoolExecutor ex =
    new ThreadPoolExecutor(limit, limit, 20, TimeUnit.SECONDS, q);
for (int i = 0; i < limit; i++) {
  ex.execute(new RunnableObject(i + 1));
}
// you are missing this line!!
ex.shutdown();
ex.awaitTermination(2, TimeUnit.SECONDS);

次のようなことを行って、すべてのジョブが完了するのを待つこともできます。

List<Future<Object>> futures = new ArrayList<Future<Object>>();
for (int i = 0; i < limit; i++) {
  futures.add(ex.submit(new RunnableObject(i + 1), (Object)null));
}
for (Future<Object> future : futures) {
   // this joins with the submitted job
   future.get();
}
...
// still need to shutdown at the end
ex.shutdown();

また、ミリ秒間スリープしていて2354、 のすべてのジョブの終了を待っているだけなので2 SECONDSawaitTerminationは常に を返しfalseます。Long.MAX_VALUE仕事が終わるのを待っていました。

最後に、新しいものを作成することを心配しているようで、ThreadPoolExecutor代わりに最初のものを再利用したいと考えています。しないでください。GC のオーバーヘッドは、ジョブが終了したかどうかを検出するために作成するコードと比較して、非常に最小限に抑えられます。


javadocs から引用するには、次のようにしThreadPoolExecutor.shutdown()ます。

以前に送信されたタスクが実行される正常なシャットダウンを開始しますが、新しいタスクは受け入れられません。すでにシャットダウンされている場合、呼び出しによる追加の効果はありません。

メソッドではThreadPoolExecutor.awaitTermination(...)、executor の状態が になるのを待っていTERMINATEDます。しかし、最初に状態が呼び出された場合または呼び出された場合に移動する必要がありSHUTDOWNます。shutdown()STOPshutdownNow()

于 2012-06-07T15:05:07.873 に答える
3

エグゼクター自体とは何の関係もありません。インターフェイスのjava.util.concurrent.ExecutorService.invokeAll(Collection<? extends Callable<T>>). Callableすべてのs が終了するまでブロックします。

Executor は長寿命であることを意図しています。タスクのグループの存続期間を超えています。shutdownアプリケーションが終了し、クリーンアップするためのものです。

于 2012-06-07T15:13:15.853 に答える
2

InterruptedException がスローされた場合に再試行を処理する、受け入れられた回答のバリアントを次に示します。

executor.shutdown();

boolean isWait = true;

while (isWait)
{
    try
    {             
        isWait = !executor.awaitTermination(10, TimeUnit.SECONDS);
        if (isWait)
        {
            log.info("Awaiting completion of bulk callback threads.");
        }
    } catch (InterruptedException e) {
        log.debug("Interruped while awaiting completion of callback threads - trying again...");
    }
}
于 2015-02-08T06:38:55.167 に答える
1

別のアプローチは CompletionService を使用することです。これは、タスクの結果を試行する必要がある場合に非常に役立ちます。

//run 3 task at time
final int numParallelThreads = 3;

//I used newFixedThreadPool for convenience but if you need you can use ThreadPoolExecutor
ExecutorService executor = Executors.newFixedThreadPool(numParallelThreads);
CompletionService<String> completionService = new ExecutorCompletionService<String>(executor);

int numTaskToStart = 15;

for(int i=0; i<numTaskToStart ; i++){
    //task class that implements Callable<String> (or something you need)
    MyTask mt = new MyTask();

    completionService.submit(mt);
}

executor.shutdown(); //it cannot be queued more task

try {
    for (int t = 0; t < numTaskToStart ; t++) {
        Future<String> f = completionService.take();
        String result = f.get();
        // ... something to do ...
    }
} catch (InterruptedException e) {
    //termination of all started tasks (it returns all not started tasks in queue)
    executor.shutdownNow();
} catch (ExecutionException e) {
    // ... something to catch ...
}
于 2014-06-15T10:09:35.597 に答える
-1

これを試して、

ThreadPoolExecutor ex =
    new ThreadPoolExecutor(limit, limit, 20, TimeUnit.SECONDS, q);
for (int i = 0; i < limit; i++) {
  ex.execute(new RunnableObject(i + 1));
}

追加する行

ex.shutdown();
ex.awaitTermination(timeout, unit)
于 2012-06-07T15:15:37.853 に答える