まず、スレッドプールの4種類を取得するためのコードを見て:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
复制代码
エグゼキュークラスによって生成された4つのスレッドプールで見つけることができます。順次全て同じThreadPoolExecutor()コンストラクタ最終的なコールを、発見の4つの内部実装方法を開く、その差は、コンストラクタの異なるパラメータです。私たちは、パラメータのThreadPoolExecutorのリストを見てみましょう。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
复制代码
これらの異なるパラメータは、スレッドプールの4種類の異なる作業機構につながるのだからです。コメントパラメータのリファレンスソースは、我々は、パラメータの意味を示します。
- corePoolSize:スレッドプールのスレッドに常駐内のスレッドのコア数、彼らはアイドル状態であっても、それはセットallowCoreThreadTimeOutの値がない限り、破壊されることはありません。
- maximumPoolSize:スレッドプール内のスレッドの最大数
- keepAliveTimeが:指定された最大アイドル時間後に破壊された非コア糸、追加のスレッドのコアの数よりも多いです。(想定時間5S、芯糸2は、現在のスレッドが4であり、残りの2つのコアのスレッドよりスレッドの数は5秒間アイドル状態の後に破壊されます。)
- 単位:時間の単位
- ワークキュー:待ち行列
- threadFactory:世代のスレッドファクトリ
- ハンドラ:キューがフル稼働で、スレッドプールの数は、新しいタスクに対処する方法を、最大値に達します。
- AbortPolicy(デフォルト):直接には例外がスローされます
- CallerRunsPolicy:スレッドへの呼び出し側の場所。(現在の呼び出し側スレッドがメインであると仮定すると、メイン処理にオン)
- DiscardOldestPolicy:最長時間のためのタスクを処理して廃棄し、その後、現在のタスクを実行します。(最小最近、キューノードで処理されたソースコードを表示するには、キューの先頭が実際にポーリング()メソッドを呼び出して、実際にあります)
- DiscardPolicy:仕事を失うと、例外をスローしません。
スレッドプールのメカニズム:
スレッドプールは、タスクを追加し続けた場合、
スレッドの現在の数は、スレッドがコアの数、新しいスレッド未満のとき。
スレッドの現在の数は、カーネルスレッドの数に達した場合に待ちキューにタスク。
キューがいっぱいになると、新しいスレッドを作成し続けています。
プールは、スレッドの最大数に達するとも待っているキューがいっぱいになると、サービスポリシーの拒否を取ります。
次はパラメータに基づいて、異なるスレッドプールを分析する必要があります。
FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
复制代码
我々は、corePoolSizeコアスレッドの数とmaximumPoolSizeが一貫しているスレッドの最大数、およびkeepAliveTimeがゼロを見ることができます。ワークキューはLinkedBlockingQueueあり、これはチェーンのブロッキングキューです。これは結論付けることができます:スレッドプールは、スレッドプールの固定の数であり、無限の待ちキューがあります。私たちは、処理タスクの着実な量のためのスレッドプールのシーンを推定することができます。例えば、平均1秒のタスク10を受信し、タスクは、曲線の量が急ではない受け取りました。
適したシーン:(多くのスレッドの数が、損失は制御のスレッドの一定数のため、スレッドコンテキストの切り替え時にあれば、遅い大タスキング)の数が少ないため、大きな課題。
CachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
复制代码
私たちは、それがコアスレッドプールのスレッドが存在しないことを示し、corePoolSizeコアスレッドプールを見ることができ、回収することができ、スレッド手段が、時には、スレッド・プールが空になり、破壊されています。そして、maximumPoolSize intは、スレッドプールの代表者と同等の最大値は、無制限のスレッドを作成することができます。keepAliveTimeが60、アイドル60秒回復スレッドに代わって。ワークキューはSynchronousQueueは、同期キューが、過ごすにスレッドを待ち、その後、タスクを追加していくために、タスクの到着後、あるキューの容量、ではないです。私たちは、通常は割り当てを処理しないためにスレッドプールを導き出すが、割り当てシーンの時々の瞬間サージ。
適切なシーン(頻繁なスレッド半分ことなく迅速に各タスク処理、他のスレッドに切り替える)小タスクの多数。
ScheduledThreadPool
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
复制代码
私たちは、最大の違いは、スレッドプールのパラメータのワークキューがDelayedWorkQueueであるということであることがわかります。キューは、大きなスタックに小さなによる時間遅れです。そして、遅延時間は、ヘッドノードのキュー0未満のノードを返すとき。だから、スレッドプールは、定期的なタスクのための時間を指定することもできます。また、定期的なタスクを実行するタスクを追加する増分遅延時間をすることができます。
適したシナリオ:タイミング・サイクル・タスクまたはタスク。
SingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
复制代码
我々が見ることができるスレッドのコア数とスレッドmaximumPoolSize corePoolSizeスレッドプールは、スレッドの代わりに、1の最大数がシングルスレッドであるため、スレッドプールの実装は、シリアル動作、全く同時実行しないので、唯一つの固定ねじを有しています効果。ワークキューはLinkedBlockingQueueあり、これはチェーンのブロッキングキューです。タスクのシリアル実行キューのスレッドプールそう。
適したシナリオ:連続したシリアルタスク。
読者はkeepAliveTimeが0の意味が表現されて不思議に思うかもしれませんか?それはすぐにスレッドをリサイクルしたり、それを回復することはありませんか?
keepAliveTimeがパラメータ注釈は明らかに非中核スレッドにのみ有用示しています。代表が0回復されることはありませんならば、我々は、ScheduledThreadPoolソースから推測することができ、その後、一度非コアスレッドから作成ScheduledThreadPoolは回復しなかったでしょうか?これは非常に無理があります。だから私はすぐに回復のために、0と考えています。
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
复制代码