0

ExecutorServiceオブジェクトを実行しようとしたところFixedThreadPool、問題が発生しました。

プログラムがナノ秒で実行されることを期待していましたが、ハングしました。Semaphoreキュー内のアイテムが合計されないように、それと一緒に使用する必要があることがわかりました。

プールのすべてのスレッドが使用されていることを知る方法はありますか?

基本コード...

static ExecutorService pool = Executors.newFixedThreadPool(4);
static Semaphore permits = new Semaphore(4);
try {
    permits.acquire();
    pool.execute(p);  // Assuming p is runnable on large number of objects
    permits.release();
} catch ( InterruptedException ex ) {
}

このコードはハングアップしますが、その理由は本当にわかりません。プールが現在すべてのスレッドが終了するのを待っているかどうかを知る方法は?

4

3 に答える 3

3

デフォルトでは、4 つを超えるタスクをプールに送信すると、余分なタスクはスレッドが使用可能になるまでキューに入れられます。

コメントで参照したブログでは、セマフォを使用して、一度にキューに入れることができる作業の量を制限しています。これは、何千ものタスクがキューに入れられ、使用可能なメモリを使い始めるまでは問題になりません。とにかく、これを行うためのより簡単な方法があります -バインドされたキューでThreadPoolExecutorを構築します。*しかし、これはあなたの問題ではありません。

タスクがいつ完了するかを知りたい場合は、タスクの完了を待つために使用できるオブジェクトをExecutorService.submit()返すことに注意してください。Future

Future<?> f = pool.execute(p);
f.get();
System.out.println("task complete");

いくつかのタスクがあり、それらすべてが完了するのを待ちたい場合は、それぞれ Futureをリストに保存get()してから順番に呼び出すか、調査しますExecutorService.invokeAll()(基本的に同じことを 1 回のメソッド呼び出しで行います)。

タスクが完了したかどうかもわかります。

Future<?> f = pool.execute(p);

while(!f.isDone()) {
    // do something else, task not complete
}

f.get();

shutdown()最後に、タスクが完了しても、スレッド プールを呼び出していない場合、プログラムが終了しない (そのため、「ハング」したように見える) 場合があることに注意してください。その理由は、スレッドがまだ実行中であり、さらに作業が与えられるのを待っているためです。

*編集:申し訳ありませんが、回答を読み直して、この部分が間違っていることに気付きました-ThreadPoolExecutor タスクをキューに提供し、受け入れられない場合は拒否するため、境界付きキューはセマフォアプローチとは異なるセマンティクスを持ちます.

于 2010-11-13T21:20:19.860 に答える
1

セマフォは必要ありません。

ハングしている場合は、おそらくスレッドが他の場所でロックされているためです。

デバッガーでコードを実行し、ハングしたときに一時停止して、スレッドが何をしているかを確認します。

于 2010-11-13T19:59:30.007 に答える
0

ThreadPoolExecutorを使用するように変更できます。アクティブなスレッドのおおよそgetActiveCount()の数を返すメソッドが含まれています。なぜおおよそなのかはわかりません。

于 2010-11-13T20:03:12.097 に答える