Javaスレッド池の拒否戦略は詳細な解を実現する。
一、概要
jdk 1.5バージョンはJUCの同時プログラミングパッケージを追加しました。伝統的なマルチスレッドの開発を大いに簡略化しました。
Javaスレッド池は典型的な池化思想の産物であり、同様にデータベースの接続池、redisの接続池などがあります。池化思想とは、最初に資源を申請して、使用可能な接続を作成することです。このように使う時は、接続情報を作成するためのオーバーヘッドは必要ありません。生活の中で鲜明な例を挙げて、有名な洋ファストフードのある基あるいはある労働に行く时、配给人はバイトで中间の保温箱の中から直接取って、それから包装してよくなりました。もう臨時で注文書を持って来なくてもいいです。また原材料を取りに行きます。また加工をします。効率が著しく向上しました。
池である以上、必ず最大値、初期値、生存値などの属性があります。特定の条件に達した時にまた要請すると、池はどうやって請求処理しますか?ここで池の拒否策を引き出しました。一般的なデータベース接続池は、最大接続数に達するとデフォルトで特定の設定を待つ時間や直接に異常が発生します。本稿で述べるスレッド池は、このような戦略ではなく、以下から説明します。
二、スレッド池の拒否戦略
スレッドプールには三つの重要なパラメータがあり、決定は拒否戦略に影響を与えた。corePoolSize-コアスレッド数、すなわち最小スレッド数である。workQue-列をふさぐ。maximPoolSize-最大スレッド数
コミットタスク数がcorepoolSizeより大きい場合、優先的にworkQueブロック列にタスクを入れます。ブロック列が飽和すると、スレッドの数が最大スレッド数に達するまで拡張されます。この時、余分なタスクを行うと、スレッド池の拒否策がトリガされます。
まとめて言えば、提出したジョブ数が(workQue.size()+maximPoolSize)より大きい場合、スレッド池の拒否策がトリガされます。
三、戦略の定義を拒否する
拒否戦略は、特定の拒否戦略をカスタマイズする実行ロジックである上位インターフェースRejectedExectionHandlerを提供する。
jdkデフォルトは、4つの拒否戦略を提供しています。CallerRuns Policy-拒否ポリシーをトリガすると、スレッドが閉じられていない限り、スレッドを使ってタスクを直接実行します。
一般的に併発するのは比較的に小さくて、性能の要求は高くなくて、失敗を許しません。ただし、スケジューラは自分でタスクを実行していますので、スピードを出しすぎると、プログラムがブロックされてしまい、パフォーマンス効率的に必然的な損失が大きいです。
AbortPolicy-ジョブを破棄し、RejectedExecution Exception異常情報の実行を拒否します。スレッドのデフォルトの拒否ポリシー。投げられた異常をうまく処理しないと、現在の実行プロセスを中断し、後続のタスクの実行に影響を与えます。
DiscardPolicy-直接廃棄します。他には何もありません。
DisccardOldest Policy-拒否策がトリガされた場合、スレッドが閉じられていない限り、ブロックされた列のworkQueの中で最も古いタスクを破棄し、新しいタスクを追加します。
四、テストコード
1、AbortPolicy
2、CallerRuns Policy
本体コードと同上、拒否戦略を交換する:
3、DiscrdPolicy
拒否策を変更
4、DiscrdOldest Policy
同様に、拒否戦略を変更します。
五、まとめ
四つの拒否戦略は互いに独立して、どのような戦略を選択して実行しますか?実際の作業では、ExectorServiceを直接使用する場合、デフォルトのdefault Handler、つまりAbortPolicyポリシーを使用します。
jdk 1.5バージョンはJUCの同時プログラミングパッケージを追加しました。伝統的なマルチスレッドの開発を大いに簡略化しました。
Javaスレッド池は典型的な池化思想の産物であり、同様にデータベースの接続池、redisの接続池などがあります。池化思想とは、最初に資源を申請して、使用可能な接続を作成することです。このように使う時は、接続情報を作成するためのオーバーヘッドは必要ありません。生活の中で鲜明な例を挙げて、有名な洋ファストフードのある基あるいはある労働に行く时、配给人はバイトで中间の保温箱の中から直接取って、それから包装してよくなりました。もう臨時で注文書を持って来なくてもいいです。また原材料を取りに行きます。また加工をします。効率が著しく向上しました。
池である以上、必ず最大値、初期値、生存値などの属性があります。特定の条件に達した時にまた要請すると、池はどうやって請求処理しますか?ここで池の拒否策を引き出しました。一般的なデータベース接続池は、最大接続数に達するとデフォルトで特定の設定を待つ時間や直接に異常が発生します。本稿で述べるスレッド池は、このような戦略ではなく、以下から説明します。
二、スレッド池の拒否戦略
スレッドプールには三つの重要なパラメータがあり、決定は拒否戦略に影響を与えた。corePoolSize-コアスレッド数、すなわち最小スレッド数である。workQue-列をふさぐ。maximPoolSize-最大スレッド数
コミットタスク数がcorepoolSizeより大きい場合、優先的にworkQueブロック列にタスクを入れます。ブロック列が飽和すると、スレッドの数が最大スレッド数に達するまで拡張されます。この時、余分なタスクを行うと、スレッド池の拒否策がトリガされます。
まとめて言えば、提出したジョブ数が(workQue.size()+maximPoolSize)より大きい場合、スレッド池の拒否策がトリガされます。
三、戦略の定義を拒否する
拒否戦略は、特定の拒否戦略をカスタマイズする実行ロジックである上位インターフェースRejectedExectionHandlerを提供する。
jdkデフォルトは、4つの拒否戦略を提供しています。CallerRuns Policy-拒否ポリシーをトリガすると、スレッドが閉じられていない限り、スレッドを使ってタスクを直接実行します。
一般的に併発するのは比較的に小さくて、性能の要求は高くなくて、失敗を許しません。ただし、スケジューラは自分でタスクを実行していますので、スピードを出しすぎると、プログラムがブロックされてしまい、パフォーマンス効率的に必然的な損失が大きいです。
AbortPolicy-ジョブを破棄し、RejectedExecution Exception異常情報の実行を拒否します。スレッドのデフォルトの拒否ポリシー。投げられた異常をうまく処理しないと、現在の実行プロセスを中断し、後続のタスクの実行に影響を与えます。
DiscardPolicy-直接廃棄します。他には何もありません。
DisccardOldest Policy-拒否策がトリガされた場合、スレッドが閉じられていない限り、ブロックされた列のworkQueの中で最も古いタスクを破棄し、新しいタスクを追加します。
四、テストコード
1、AbortPolicy
package com.cfang;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class T2 {
public static void main(String[] args) throws Exception{
int corePoolSize = 5;
int maximumPoolSize = 10;
long keepAliveTime = 5;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(10);
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler);
for(int i=0; i<100; i++) {
try {
executor.execute(new Thread(() -> log.info(Thread.currentThread().getName() + " is running")));
} catch (Exception e) {
log.error(e.getMessage());
}
}
executor.shutdown();
}
}
exector.execute()がタスクを提出すると、RuntimeExceptionをスローしますので、try.cachが異常情報を処理しないと、調達者の処理プロセスを中断し、その後のタスクは実行できません。自分でテストしてもいいです。2、CallerRuns Policy
本体コードと同上、拒否戦略を交換する:
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
運転後、コンソールのconsoneで見られるのは、一部のデータが印刷されて、「main is running」と表示されています。つまり、呼び出しスレッド処理が反映されています。3、DiscrdPolicy
拒否策を変更
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
直接ジョブを廃棄し、実際の運転中に印刷された情報は100件ありません。4、DiscrdOldest Policy
同様に、拒否戦略を変更します。
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();
実際に実行しても、印刷された情報は100本を下回ります。五、まとめ
四つの拒否戦略は互いに独立して、どのような戦略を選択して実行しますか?実際の作業では、ExectorServiceを直接使用する場合、デフォルトのdefault Handler、つまりAbortPolicyポリシーを使用します。