多数のタスクを実行するスレッド(約5〜150)を生成するプログラムがあります。もともと、私はFixedThreadPool
を使用していました。これは この同様の質問 がより長寿命のタスクに適していることを示唆し、マルチスレッドの知識が非常に限られているため、スレッドの平均寿命(数分) "長命)。
ただし、最近、追加のスレッドを生成する機能を追加しました。これにより、設定したスレッド制限を超えてしまいます。この場合、許可できるスレッド数を推測して増やしたり、CachedThreadPool
に切り替えて無駄なスレッドをなくした方が良いでしょうか?
両方を試してみて、違いはありませんseemはありませんので、避けるためにCachedThreadPool
無駄。ただし、スレッドの寿命は、代わりにFixedThreadPool
を選択し、未使用のスレッドを処理する必要があることを意味しますか? この質問 は、これらの余分なスレッドが無駄にされていないように見えますが、説明をいただければ幸いです。
CachedThreadPoolは、長時間実行されるスレッドに使用しても悪影響はないため、状況に合わせて使用する必要があります。 CachedThreadPoolsが短いタスクに適しているというJava docのコメントは、それらがそのような場合に特に適していることを示唆しているだけで、長時間実行されるタスクを含むタスクには使用できない、または使用すべきではありません。
さらに詳しく説明すると、 Executors.newCachedThreadPool と Executors.newFixedThreadPool は両方とも、同じスレッドプール実装(少なくともオープンJDKでは)によって、異なるパラメーターを使用してサポートされています。違いは、スレッドの最小値、最大値、スレッドのキル時間、およびキューのタイプだけです。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
FixedThreadPoolには、実際に固定数のスレッドで作業する場合に利点があります。これは、指定したレベルでスレッド数が維持されることを認識しながら、任意の数のタスクをexecutorサービスに送信できるためです。スレッドの数を明示的に増やしたい場合、これは適切な選択ではありません。
ただし、これは、CachedThreadPoolで発生する可能性がある1つの問題が、同時に実行されるスレッドの数を制限することに関することを意味します。 CachedThreadPoolはそれらを制限しません。そのため、あまり多くのスレッドを実行しないように、独自のコードを記述する必要がある場合があります。これは、アプリケーションの設計と、executorサービスへのタスクの送信方法に大きく依存します。
FixedThreadPool
とCachedThreadPool
の両方は、負荷の高いアプリケーションでは悪です。
CachedThreadPool
はFixedThreadPool
よりも危険です
アプリケーションの負荷が高く、低レイテンシが必要な場合は、以下の欠点があるため、両方のオプションを取り除く方が良い
CachedThreadPool
の制御を失います。両方が悪であることを知っているので、より小さい悪は良いことをしません。 ThreadPoolExecutor を優先します。これにより、多くのパラメーターをきめ細かく制御できます。
beforeExecute(Thread, Runnable)
とafterExecute(Runnable, Throwable)
をオーバーライドしますだから、たくさんのタスクを実行するスレッド(〜5-150)を生成するプログラムがあります。
選択したOSおよびハードウェアによってスレッドが実際に処理される方法を理解していますか? JavaがスレッドをOSスレッドにマップする方法、スレッドをCPUスレッドにマップする方法などONE JREで150個のスレッドを作成することは、その下に大規模なCPUコア/スレッドがある場合にのみ意味があるため、ほとんどの場合そうではないからです。 OSおよび使用中のRAMによっては、n個を超えるスレッドを作成すると、OOMエラーが原因でJREが終了することさえあります。したがって、スレッドとそれらのスレッドが行う作業、処理できる作業の数などを実際に区別する必要があります。
それがCachedThreadPoolの問題です。これらのスレッドを処理できるCPUコアが2つしかないため、実際には実行できないスレッドで長時間実行される作業をキューに入れるのは意味がありません。 150のスケジュールされたスレッドで終わる場合、Java内で使用されるスケジューラーとOSがそれらを同時に処理するために多くの不必要なオーバーヘッドを作成する可能性があります。これは、スレッドが常にI/Oなどを待機していない限り、CPUコアが2つしかない場合は不可能です。しかし、その場合でも、多くのスレッドは多くのI/Oを作成します...
そして、その問題は、例えばで作成されたFixedThreadPoolでは発生しません。 2 + nスレッド。nはもちろん妥当な低さです。ハードウェアとOSのリソースは、とにかく実行できないスレッドを管理するためのオーバーヘッドがはるかに少ないためです。