エレガントなJavaのスレッドプール

はじめに
スレッドプールは確かに我々が使用している、JDKもエグゼキュータ・スレッド・プールの数が付属しています。あなたが今まで疑問に思っている場合でも、スレッド・プールに最もエレガントな方法は、それを使用しているか、わからないのですか?自分のスレッドプールの設定方法への生産環境は、それが合理的ですか?
今日の週末は、私の思考「エレガント」を総括するだけの時間、任意の質問が正しい私に歓迎します。

プールの使用規則をスレッド
ので、いくつかのルールに従ってください、より良いスレッドプールを使用します:

スレッドサイズの数を設定し
、スレッドプールの設定パラメータを
埋め込まれたフックを使用して、あなたの行動は、
近いスレッド・プール
に関連するスレッドプールの構成
設定スレッドプールサイズ
これは、実際にテストセンターのインタビューでは、インタビュアーはcoreSizeにあなたのスレッドプールサイズの多くを聞いてきますスレッドプールのご理解を調べます。
まず、この問題への具体的には、我々は、計算集約型またはIO集約型であり、これだけの数を知った、私達ができる優れたスレッドプールの上限を設定することが我々のニーズをクリアする必要があります。

1は、計算集約型
あれば名前が示唆するように、アプリケーションがコンピューティングリソースのCPU、マルチコアCPU時代の多くを必要とされ、私たちは各CPUコアが計算に関与しているようにする必要があり、十分に活用CPU性能は、これは、サーバ構成の廃棄物とは見なされません非常に優れたサーバ構成にもちょうど重要な廃棄物のようになりますシングルスレッドプログラムを実行しています。計算集約型アプリケーションでは、それは完全に、利点を果たし、過剰なスレッドコンテキストの切り替えを避けるようにするために、コアCPUの数に完全に動作するように、理想的なソリューションです。

スレッドの数が=数+1 CPUコアはまた、CPUコアの数×2に設定することができるが、それは、JDKのバージョンに依存し、CPUの構成(サーバのCPUハイパースレッディング)。

一般設定CPU * 2とすることができます。

2は、IO集約型の
我々は、すべてのWebアプリケーションをやっているほとんどの開発者は、ネットワークトラフィックを大量に必要とする、IOが1回発生するだけでなく、データベースと、また、キャッシュとの間の相互作用は、IOを必要とする、ことを、スレッドが待機状態になりますIOの終わりには、データの準備ができたときに、スレッドが継続されます。したがって、IO負荷の高いアプリケーションのためにここで見つけることができ、我々はIOを待つために、この時点で作ることができるように、スレッドプールの一部をマルチスレッドの数を設定することができ、スレッドが並列処理の効率を向上させるために、他のことを行うことができます。その後、プールにスレッドされていないデータの量を容易に設定することができますか?もちろん、スレッドコンテキストスイッチは価格で来ることを忘れないようにしてくださいではありません。現在IO集中アプリケーションのための式合計:
スレッド= CPUコア/(L閉塞因子)閉塞率とは、一般的に0.8〜0.9であり、0.8または0.9を取ることができます。
デュアルコアCPUのための式を適用し、それはスレッドの理想的な数は20であります、もちろん、絶対的ではなく、実際の状況と実際のビジネスに応じて調整する必要がある:最終INTプールサイズ=(INT) (CPUコア/(1から0.9)

あなたはすなわち、「Java仮想マシン並行プログラミング」「JVMマスタリングに並行処理プログラミング」、阻害要因のために一つの文で述べました。

ブロック係数については、我々は最初に推測してみてください、またはシステムがスレッド/ IOオペレーションの消費量を費やしている上、時間とCPU集約型のタスクの時間比率を決定するために、いくつかの入札分析ツールやjava.lang.managementのAPIを使用することができます。

スレッドプールの設定パラメータは
、それはこれに来るとき、私達はちょうどことを心に留めておく必要がありますが、設定項目に上限を選択していないしてはなりません
メソッドは、スレッド実行プログラムを作成する際に使用することは推奨されていないのはこのためです。
例えば、あるため、いくつかの予期せぬ事態のExecutors.newCachedThreadPool設定とアンバウンド形式のキューの設定は、システムのスレッドプールは、スレッドの状況やタスクキューがメモリの枯渇システムのクラッシュや例外につながる、拡大し続けているサージにつながる、異常になります。私たちは、この問題を回避するために、カスタム・スレッド・プールを使用することをお勧めし、標準化されたスレッドプールの使用で上書き原則であります!金庫は今、オーバー自信がありません!
執行は、スレッドプールを作成するために、4つの方法で見ることができます:

//使用无界队列
パブリック静的ExecutorServiceのnewFixedThreadPool(int型にnthreads){
        て、新しいThreadPoolExecutorを返す(nthreadsの値、nthreadsの値、
                                      0L、TimeUnit.MILLISECONDS、
                                      新しいLinkedBlockingQueue <Runnableを>());
    }

スレッドプールの//無数
公共の静的ExecutorServiceのnewCachedThreadPool(){
        新しいて、新しいThreadPoolExecutor(0は、Integer.MAX_VALUE、戻り
                                      60L、TimeUnit.SECONDS、
                                      新しい新しいSynchronousQueue <Runnableを>は());
    }
そうでなければ、もはや表示されている、誰ソースコードを確認して自由に。

第二に、スレッドの合理的なセット数、およびアイドル回復時間をスレッド、設定するタスクの実行サイクルや時間に応じて、頻繁に回復と創造を回避するために、我々はスレッドプールを使用することを目指すもののは、システムのパフォーマンスとスループットを向上させることであるが、また、それ以外の場合は、予期せぬ問題が発生し、システムの安定性を検討することは、トラブルになります!
第三には、実際の場面に応じて、彼らの拒否ポリシーに適して選択します。補償するために、自動補償機構JDKサポート台無しにしないでください!カスタム戦術を実行するすべての詳細を明らかにすることを拒否使用してみてください!
第四に、スレッドプールは、ポリシーを否定し、カスタムポリシーはのRejectedExecutionHandlerインタフェースを実装するために拒否することができます。
JDKは拒否戦略が付属して、次の通りである:
AbortPolicy:直接はスロー正しく動作してからシステムを防ぎます。
CallerRunsPolicy:スレッドプールが閉じていない限りは、長い間、呼び出し側のスレッドで直接政策は、現在のタスクが破棄されて実行されます。
DiscardOldestPolicy:最古の要求を破棄し、再度、現在のジョブをサブミットしてみてください。
DiscardPolicy:タスクを処理できない廃棄、どんな治療を与えられていません。

使用フック
トラックを実行するスレッドプールを残して、フックの使用を:
ThreadPoolExecutorは、タスクを実行した後に実行される前に、ユーザーが何かをすることができ、フックメソッド保護されたタイプを上書きすることができます提供します。私たちは、このような伐採や他の操作として、統計情報を収集し、そのような初期化にThreadLocalを達成するためにそれを使用することができます。そのようなフックとafterExecuteとしてBeforeExecute。タスクがrerminatedとして論理は、ユーザが挿入することを可能にする実行が終了したときフックを使用することができるもあります。
フックメソッドが失敗した場合、内部スレッドの実装が失敗するか、中断されます。

私たちはあなたにもELKログや他のシステムへの記録が終了した後の状態を直接実行することができ、前と後のスレッドの前にいくつかの動作条件を記録するためにbeforeExecuteとafterExecuteを使用することができます。

閉じるスレッドプールの
スレッドプールが引用されていないと、ワーカースレッドの数が0である、スレッドプールが終了する内容。また、スレッドプールを終了し、手動でシャットダウンを呼び出すことができます。我々は、スレッドのリソースが解放されている可能にするために、シャットダウンを呼び出すことを忘れた場合は、我々はまた、それぞれの目標を達成するためにkeepAliveTimeが及びallowCoreThreadTimeOutを使用することができます!
もちろん、慎重なアプローチは、仮想マシンRuntime.getRuntime()。AddShutdownHookメソッドを使用することで、手には、スレッドプールのcloseメソッドをコールします!

私たちは、ThreadPoolExecutorによってカスタム・スレッド・プールを実装することができます

ThreadPoolTask​​Executorは春のコアパックで、JDK ThreadPoolExecutor JUCです。ThreadPoolTask​​ExecutorはThreadPoolExecutorプロセスがカプセル化されています。

 

最後に、私はアイテム添付の使用を生成します

ThreadPoolTaskConfig
package com.zcckj.common.db.config.thread;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;


@Configuration
@Slf4j
public class ThreadPoolTaskConfig {

	@Value("${task.core_pool_size}")
	private Integer corePoolSize;
	@Value("${task.max_pool_size}")
	private Integer maxPoolSize;
	@Value("${task.queue_capacity}")
	private Integer queueCapacity;
	@Value("${task.keep_alive_seconds}")
	private Integer keepAliveSeconds;


	@Bean(name="taskExecutor")
	public ThreadPoolTaskExecutor taskExecutor(){
		ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
		//线程池维护线程的最少数量
		poolTaskExecutor.setCorePoolSize(corePoolSize);
		//线程池维护线程的最大数量
		poolTaskExecutor.setMaxPoolSize(maxPoolSize);
		//线程池所使用的缓冲队列
		poolTaskExecutor.setQueueCapacity(queueCapacity);
		//线程池维护线程所允许的空闲时间
		poolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
		poolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
		return poolTaskExecutor;
	}

}

使用


    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    …………

    taskExecutor.execute(() -> dosomething……);

 

この記事では、自己を参照:https://blog.csdn.net/u012881584/article/details/85221635

公開された33元の記事 ウォンの賞賛6 ビュー10000 +

おすすめ

転載: blog.csdn.net/kuangni5808/article/details/102541443