私の質問:ThreadPoolExecutor
でスレッド化されたオブジェクトの束を実行し、それらがすべて完了するまで待つ方法移動する前に終了しますか?
ThreadPoolExecutorは初めてです。したがって、このコードは、それがどのように機能するかを学ぶためのテストです。 execute()
を別のBlockingQueue
で呼び出さずにキューを開始する方法がわからないため、現時点ではRunnableObject
にオブジェクトを入力しません。とにかく、今はawaitTermination()
を呼び出していますが、まだ何かが足りないと思います。どんなヒントも素晴らしいでしょう!ありがとう。
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");
}
}
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.");
}
あなたの問題は、プールにすべてのジョブを送信した後、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
_ SECONDS
のすべてのジョブの終了を待っているだけなので、awaitTermination
は常にfalse
。
最後に、新しいThreadPoolExecutor
の作成を心配していて、代わりに最初のものを再利用したいようです。しないでください。 GCのオーバーヘッドは、ジョブが終了したかどうかを検出するために記述するコードと比較して、非常に小さくなります。
Javadocsから引用するには、ThreadPoolExecutor.shutdown()
:
以前に送信されたタスクが実行されますが、新しいタスクは受け入れられない、正常なシャットダウンを開始します。呼び出しは、既にシャットダウンされている場合、追加の効果はありません。
ThreadPoolExecutor.awaitTermination(...)
メソッドでは、executorの状態がTERMINATED
に移動するのを待っています。ただし、最初にshutdown()
が呼び出された場合はSHUTDOWN
に、_shutdownNow()
が呼び出された場合はSTOP
に状態を移行する必要があります。
エグゼキューター自体とは何の関係もありません。インターフェイスのJava.util.concurrent.ExecutorService.invokeAll(Collection<? extends Callable<T>>)
を使用するだけです。すべてのCallable
sが終了するまでブロックします。
エグゼキューターは長命であることを意図しています。タスクのグループの寿命を超えています。 shutdown
は、アプリケーションが終了してクリーンアップするときのためのものです。
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...");
}
}
別のアプローチは、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 ...
}