Javaのスレッドプールについて話します
4984 ワード
スレッドプールとは?
スレッドプールは、作業スレッドのセットが保存されているコンテナで、タスクが来るたびにコンテナから使用可能なスレッドを取り出してタスクを実行します.
スレッドプールの役割?スレッドプールは、頻繁なスレッドの作成、削除が必要なため、パフォーマンスオーバーヘッド を削減するため、大量の非同期タスクを実行する際に顕著なパフォーマンス向上をもたらす.は、システムの安定性 を保障するためのリソース制御可能な方法を提供する.は、完了したタスク数 のようなスレッドプールの基礎状態データを取得する.
リソース制御vs安定性?
なぜリソース制御とシステムの安定したパフォーマンスが関連しているのでしょうか.ここで例を挙げると、Tomcatがスレッドプールを使用していない場合、要求が入るたびにスレッドが作成されます.10000スレッドが同時に作成されている場合は、スレッドの作成に問題はありません.結局、各スレッドのスタックスペースは大きくありませんが、10000リクエストを同時に処理するのは冗談です.ほとんどの時間はCPUがコンテキスト切り替えをしている可能性があります.資源を浪費している.ここでスレッドプールが機能し始め、同時に処理されるタスク数を保証することができます.例えば、100個です.この時、資源の制御可能、システムの安定性を保障する役割を果たしたのではないでしょうか.
スレッドプールの種類
jdk中線程池には多くの種類があり、作用はすべて異なり、具体的には以下の通りである.固定サイズスレッドプール: 単一スレッドプール: キャッシュスレッドプール: 単一スレッドスケジューリングスレッドプール: マルチスレッドスケジューリングスレッドプール: 盗作スレッドプール: スレッドプールのパラメータの意味は?
実は上にこんなに多くのスレッドプールがあり、下層処理クラスは を含む、タスクがないことを発見した場合、アイドルスレッドをすべて停止します. となる. が回収される. を参照してください. です. を参照する.
スレッドプールの拒否ポリシー?
拒否ポリシーは4つあります.
直接mainスレッドの中で
提出を続けてもいいですが、私は処理しません.後続の任務が処理できるかどうかは縁次第だ.スレッドプール内のタスクが完了し、ちょうどタスクがコミットされた場合、このタスクは実行できます.後続の提出はまた直接なくした.
スレッドプールに最初にコミットされたが実行されていないタスクを捨てます.つまり、このタスクはまだ先頭に立っていますが、なぜかpollに落ち、現在コミットされているタスクをキューに追加します.
後でスレッドプールの範囲を超えたタスクを提出したら、私は管理したくないので、自分のスレッドで実行しましょう.つまり、スレッドプールの管理から離れています!Javaのデフォルトポリシーは
独自のスレッドプールの実装
スレッドプールは、作業スレッドのセットが保存されているコンテナで、タスクが来るたびにコンテナから使用可能なスレッドを取り出してタスクを実行します.
スレッドプールの役割?
リソース制御vs安定性?
なぜリソース制御とシステムの安定したパフォーマンスが関連しているのでしょうか.ここで例を挙げると、Tomcatがスレッドプールを使用していない場合、要求が入るたびにスレッドが作成されます.10000スレッドが同時に作成されている場合は、スレッドの作成に問題はありません.結局、各スレッドのスタックスペースは大きくありませんが、10000リクエストを同時に処理するのは冗談です.ほとんどの時間はCPUがコンテキスト切り替えをしている可能性があります.資源を浪費している.ここでスレッドプールが機能し始め、同時に処理されるタスク数を保証することができます.例えば、100個です.この時、資源の制御可能、システムの安定性を保障する役割を果たしたのではないでしょうか.
スレッドプールの種類
jdk中線程池には多くの種類があり、作用はすべて異なり、具体的には以下の通りである.
newFixedThreadPool
newSingleThreadExecutor
、複数のタスクが到着し、タスク実行中にスレッドが切れた場合、スレッドプールは後続のタスクを完了するために新しいスレッドを再作成します.スレッドプールにいつまでも1つのスレッドしかないことを保証するだけです.newCachedThreadPool
、どれだけのタスクが来て、私はどれだけのスレッドを作成して処理して、処理が終わった後に急いでスレッドを回収しないで、スレッドが60 sアイドルになった後に、自動的にスレッドを回収して、もしスレッドプールの中で1つのタスクがすべてないならば、そのスレッドプールはアクティブなスレッドがありません.newSingleThreadScheduledExecutor
.名前の通り、スレッドプールにはスレッドが1つしかなく、定期的にタスクを実行します.
.上記と同様に、タイミングタスクスレッドが構成できるだけです.newWorkStealingPool
.主な処理ForkJoinTask
実は上にこんなに多くのスレッドプールがあり、下層処理クラスは
ThreadPoolExecutor
で、このクラスを理解すればスレッドプールの原理も理解できます.もちろん、この問題はよく面接に出ますが、どうせ私は前に失敗したことがあるので、ここで記録しておきましょう.まず、完了したコンストラクション関数を見てみましょう.public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize
パラメータは、スレッドプールにタスクが実行されているかどうかにかかわらず、corePoolSize
個のスレッドが存在することを示し、0newCachedThreadPool
に設定することができる.allowCoreThreadTimeOut
が設定されている場合、スレッドプールは、前述のcorePoolSize
スレッドmaximumPoolSize
はスレッドプールが同時に処理できる最大スレッド数を表し、同時に処理できる最大タスク数としても理解できるが、この数を超えるとタスクはworkQueue
に並ぶkeepAliveTime
は、スレッドプール内のスレッドタスクが実行すると、どのくらいアイドルになっているかを示すunit
アイドル時間に対応する単位workQueue
タスク数がmaximumPoolSize
を操作すると、後から提出されたタスクはworkQueue
に入って並びます.キューサイズを指定すると、10を設定すると、キューがいっぱいになると、後から提出されたタスクはスレッドプールに拒否されます.ボディがどのように拒否するかは、後のhandler
パラメータthreadFactory
は、スレッドを作成するファクトリクラスを表します.指定しなくてもよく、デフォルトではExecutors.DefaultThreadFactory
が使用されます.スレッドプールによって作成されるスレッドのデフォルトはpool-poolNumber-thread-threadNumber
です.たとえば、pool-1-thread-2
handler
は、コミットされたタスクがmaximumPoolSize + workQueue.size()
を超えると、jvmが後続のコミットされたタスクをどのように処理するかを示す.具体的な拒否ポリシーは、次のスレッドプールの拒否ポリシー?
拒否ポリシーは4つあります.
ThreadPoolExecutor.AbortPolicy
直接mainスレッドの中で
RejectedExecutionException
の異常を投げ出して、これは1つの運行時の異常で、やはりとても恐ろしくて、mainスレッドは掛けて、全体の応用はすべて掛けて、だからきっと慎重にしなければなりません!ThreadPoolExecutor.DiscardPolicy
提出を続けてもいいですが、私は処理しません.後続の任務が処理できるかどうかは縁次第だ.スレッドプール内のタスクが完了し、ちょうどタスクがコミットされた場合、このタスクは実行できます.後続の提出はまた直接なくした.
ThreadPoolExecutor.DiscardOldestPolicy
スレッドプールに最初にコミットされたが実行されていないタスクを捨てます.つまり、このタスクはまだ先頭に立っていますが、なぜかpollに落ち、現在コミットされているタスクをキューに追加します.
ThreadPoolExecutor.CallerRunsPolicy
後でスレッドプールの範囲を超えたタスクを提出したら、私は管理したくないので、自分のスレッドで実行しましょう.つまり、スレッドプールの管理から離れています!Javaのデフォルトポリシーは
AbortPolicy
です独自のスレッドプールの実装
package cn.crabime;
import java.util.concurrent.*;
/**
*
*/
public class FixedBoundThreadPool {
public static void main(String[] args) {
BlockingQueue blockingQueue = new LinkedBlockingQueue<>(10);
ThreadPoolExecutor executor =
new ThreadPoolExecutor(1, 5, 2000, TimeUnit.MILLISECONDS, blockingQueue, new ThreadPoolExecutor.AbortPolicy());
//
executor.allowCoreThreadTimeOut(true);
// 100 ,
for (int i = 0; i < 100; i++) {
executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + " ");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " ");
});
}
executor.shutdown();
}
}