この記事では、参照のために4つのJavaスレッドプールの使用法を分析します。特定のコンテンツは次のとおりです
1。新しいスレッドの欠点
非同期タスクを実行するときに、次のように新しいスレッドを実行するだけですか?
新しいスレッド(new runnable(){@override public void run(){// todo auto-enerated methood stub}})。start();その後、あなたはあまりにも多くのアウトがあり、新しいスレッドの欠点は次のとおりです。
a。新しいスレッドのパフォーマンスは毎回貧弱です。
b。スレッドには統一された管理が欠けているため、制限なしに新しいスレッドを作成し、互いに競合し、クラッシュやOOMを引き起こすにはシステムリソースが多すぎる場合があります。
c。時限実行、定期的な実行、スレッドの中断など、より多くの機能が不足しています。
新しいスレッドと比較して、Javaが提供する4つのスレッドプールの利点は次のとおりです。
a。既存のスレッドを再利用して、オブジェクトの作成と絶滅のオーバーヘッドを減らし、うまく機能します。
b。同時スレッドの最大数を効果的に制御し、システムリソースの使用率を改善し、過度のリソース競争を回避し、詰まりを回避できます。
c。時限実行、定期的な実行、単一のスレッド、同時数コントロールなどの関数を提供します。
2。Javaスレッドプール
Javaは、エグゼキューターを通じて4種類のスレッドプールを提供します。
NewCachedThreadPoolは、キャッシュ可能なスレッドプールを作成します。スレッドプールの長さが処理のニーズを超えると、アイドルスレッドを柔軟にリサイクルできます。リサイクルがない場合は、新しいスレッドを作成します。
NewFixedThreadPoolは、最大数のスレッドの同時性を制御できる固定長のスレッドプールを作成し、余分なスレッドがキューで待機します。
NewsCheduledThreadPoolは、時限で定期的なタスクの実行をサポートする固定長のスレッドプールを作成します。
NewsingLethReadExecutorは、単一のスレッドスレッドプールを作成します。これは、一意のワーカースレッドのみを使用してタスクを実行し、すべてのタスクが指定された順序で実行されるようにします(FIFO、LIFO、優先度)。
(1)NewCachedThreadPool:
キャッシュ可能なスレッドプールを作成します。スレッドプールの長さが処理のニーズを超える場合、アイドルスレッドを柔軟にリサイクルできます。リサイクルがない場合は、新しいスレッドを作成します。サンプルコードは次のとおりです。
executorservice cachedthreadpool = executors.newcachedthreadpool(); for(int i = 0; i <10; i ++){final int index = i; try {thread.sleep(index * 1000); } catch(arturnedexception e){e.printstacktrace(); } cachedthreadpool.execute(new runnable(){@overridepublic void run(){system.out.println(index);}});}スレッドプールは無限です。 2番目のタスクが実行されると、最初のタスクが完了し、最初のタスクを実行するスレッドは、毎回新しいスレッドを作成せずに再利用されます。
(2)NewFixedThreadPool:
スレッドの並行性の最大数を制御できる固定長スレッドプールを作成すると、余分なスレッドがキューで待機します。サンプルコードは次のとおりです。
executorservice sixtthreadpool = executors.newfixedthreadpool(3); for(int i = 0; i <10; i ++){final int index = i; fixedthreadpool.execute(new runnable(){@overridepublic void run(){try {system.out.println(index); swree.sleep(2000);} catch(arturnedexection e){// todo auto-jenerated catch block e.printstacktrace();}};};}スレッドプールサイズは3であるため、各タスクがインデックスを出力してから2秒後にスリープするため、2秒ごとに3つの数値が印刷されます。
固定長のスレッドプールのサイズは、システムリソースに応じて最適です。 runtime.getRuntime()。可能なProcessors()など。 preloaddatacacheを参照してください。
(3)NewsCheduledThreadPool:
時限で定期的なタスクの実行をサポートする固定長スレッドプールを作成します。遅延実行のサンプルコードは次のとおりです。
ScheduleDexecutorservice ScheduleDthreadPool = executors.NewsCheduleDThreadPool(5); scheduledthreadpool.schedule(new runnable(){@overridepublic void run(){system.out.println( "delay 3秒");}}、3、timeunit.seconds);遅延実行を3秒示します。
サンプルコードは次のように定期的に実行されます。
scheduledthreadpool.scheduleatfixedrate(new runnable(){@overridepublic void run(){system.out.println( "1秒遅れ、3秒ごとにエクスパートする");}}、1、3、timeUnit.seconds);これは、遅延が1秒後に3秒ごとに実行されることを意味します。
ScheduleDexecutorServiceは、タイマーよりも安全で強力です
(4)newsinglethreadexecutor:
一意のワーカースレッドのみを使用してタスクを実行する単一のスレッドプールを作成し、すべてのタスクが指定された順序(FIFO、LIFO、優先度)で実行されるようにします。サンプルコードは次のとおりです。
executorservice singlethreadexecutor = executors.newsinglethreadexecutor(); e){// dodo auto-enerated catch block e.printstacktrace()}};}結果は順番に出力されます。これは、各タスクを順番に実行するのと同等です。
現在のほとんどのGUIプログラムはシングルスレッドです。 Androidのシングルスレッドは、データベース操作、ファイル操作、アプリケーションのバッチインストール、アプリケーションのバッチ削除などに使用できます。これらは、同時に適していないが、IOをブロックしてUIスレッドの応答に影響を与える可能性があります。
スレッドプールの機能:
スレッドプールの機能は、システムで実行されるスレッドの数を制限することです。
システム環境に応じて、スレッドの数を自動的にまたは手動で設定して、最適な操作効果を実現できます。システムリソースが無駄になり、システムの混雑が増加しています。スレッドプールを使用してスレッドの数を制御すると、他のスレッドが並んで待っています。タスクが実行された後、最初のタスクはキューから実行されて実行を開始します。キューに待機プロセスがない場合、スレッドプールのこのリソースが待機しています。新しいタスクを実行する必要がある場合、スレッドプールに待機ワーカーのスレッドがある場合、実行を開始できます。それ以外の場合は、待機キューに入ります。
スレッドプールを使用する理由:
1.スレッドが作成および破壊される回数を削減し、各ワーカースレッドを再利用して複数のタスクを実行できます。
2。スレッドプールのワーカースレッドの数は、過度のメモリ消費のためにサーバーが吸い込まれないようにするシステムの能力に応じて調整できます(各スレッドには約1MBのメモリが必要です。スレッドが開かれるほど、メモリが消費され、最終的にクラッシュが発生します。
Javaのスレッドプールのトップレベルのインターフェイスはエグゼクターですが、厳密に言えば、エグゼキューターはスレッドプールではなく、スレッドを実行するための単なるツールです。実際のスレッドプールインターフェイスはExecutorServiceです。
さらにいくつかの重要なカテゴリ:
executorservice:真のスレッドプールインターフェイス。
ScheduleDexecutorservice:Timer/Timertaskに似ている可能性があり、繰り返しのタスクを必要とする問題を解決します。
ThreadPoolexecutor:ExecutorServiceのデフォルト実装。
ScheduledThreadPoolexecutor:クラスの実装をスケジュールする定期的なタスクであるThreadPoolexecutorを継承するScheduleDexecutorServiceインターフェイスのクラス実装。
特にスレッドプールの原理があまり明確でない場合、スレッドプールを構成することは非常に複雑です。構成されたスレッドプールの方が良くない可能性が非常に高いです。したがって、いくつかの静的な工場がエグゼキュータークラスに提供され、一般的に使用されるスレッドプールを生成します。
1.NewSingLethReadExecutor
単一のスレッドプールを作成します。このスレッドプールには1つのスレッドのみが機能しています。これは、シリアルのすべてのタスクを実行する単一のスレッドに相当します。この一意のスレッドが例外のために終了する場合、それを置き換える新しいスレッドがあります。このスレッドプールにより、すべてのタスクの実行順序がタスク提出の順序で実行されることが保証されます。
2.NewFixedThreadPool
固定サイズのスレッドプールを作成します。タスクが送信されるたびに、スレッドがスレッドプールの最大サイズに達するまでスレッドが作成されます。スレッドプールのサイズは、最大値に達すると同じままです。実行例外のためにスレッドが終了すると、スレッドプールは新しいスレッドを追加します。
3.NewCachedThreadPool
キャッシュ可能なスレッドプールを作成します。スレッドプールサイズがタスクの処理に必要なスレッドを超えた場合、
その後、いくつかのアイドルスレッド(60秒でタスク実行なし)がリサイクルされます。タスクの数が増えると、このスレッドプールは、タスクを処理するために新しいスレッドをインテリジェントに追加できます。このスレッドプールは、スレッドプールサイズを制限しません。これは、オペレーティングシステム(またはJVM)が作成できる最大スレッドサイズに完全に依存します。
4.NewsCheduledThreadPool
無制限のサイズのスレッドプールを作成します。このスレッドプールは、定期的かつ定期的にタスクを実行する必要性をサポートしています。
例コード
1。固定サイズのスレッドプール、NewFixedThreadPool:
パッケージapp.executors; java.util.concurrent.executorsをインポートします。 java.util.concurrent.executorserviceをインポートします。 / ** * javaスレッド:スレッドプール * * @author xiho */ public class test {public static void main(string [] args){//固定数の再利用可能なスレッドexecutorservice pool = executors.newfixedthreadpool(2); //スレッドスレッドt1 = new MythRead()を作成します。スレッドT2 = new MythRead();スレッドT3 = new MythRead();スレッドT4 = new MythRead();スレッドT5 = new MythRead(); //実行プールのためにスレッドをプールに入れます。Execute(T1); pool.execute(t2); pool.execute(t3); pool.execute(T4); pool.execute(t5); //スレッドプールプールを閉じます。shutdown(); }} class mythread extends thread {@override public void run(){system.out.println(thread.currentthread()。getName() + "executing ..."); }}出力結果:
pool-1-thread-1が実行されています。 。 。 Pool-1-Thread-3が実行されています。 。 。 Pool-1-Thread-4が実行されています。 。 。 Pool-1-Thread-2が実行されています。 。 。 Pool-1-Thread-5が実行されています。 。 。
executorservice pool = executors.newfixedthreadpool(5)のパラメーターを変更する:executorservice pool = executors.newfixedthreadpool(2)、および出力結果は次のとおりです。
pool-1-thread-1が実行されています。 。 。 pool-1-thread-1が実行されています。 。 。 Pool-1-Thread-2が実行されています。 。 。 pool-1-thread-1が実行されています。 。 。 Pool-1-Thread-2が実行されています。 。 。
上記の結果から、NewFixedThreadPoolのパラメーターが実行できるスレッドの最大数を指定していることがわかります。この数のスレッドを追加した後、それらは実行されません。第二に、スレッドプールに追加されたスレッドは管理状態にあり、スレッドの操作は参加順序の影響を受けません。
2。シングルタスクスレッドプール、NewsInglethReadExecutor:
executorservice pool = executors.newfixedthreadpool(2)上記のコードでexecutorservice pool = executors.newsinglethreadexecutor();を変更するだけです。
出力結果:
pool-1-thread-1が実行されています。 。 。 pool-1-thread-1が実行されています。 。 。 pool-1-thread-1が実行されています。 。 。 pool-1-thread-1が実行されています。 。 。 pool-1-thread-1が実行されています。 。 。
実行メソッドを呼び出すたびに、スレッド1ランメソッドが実際に呼び出されることがわかります。
3.可変サイズスレッドプール、NewCachedThreadPool:
上記と同様に、プールの作成方法を変更するだけです。ExecutorServicePool= executors.NewCachedThreadPool();
出力結果:
pool-1-thread-1が実行されています。 。 。 Pool-1-Thread-2が実行されています。 。 。 Pool-1-Thread-4が実行されています。 。 。 Pool-1-Thread-3が実行されています。 。 。 Pool-1-Thread-5が実行されています。 。 。
この方法は、必要に応じて新しいスレッドプールを作成できるという事実によって特徴付けられますが、以前に構築されたスレッドが利用可能になると再利用されます。
4。接続プールの遅延、NewsCheduledThreadPool:
public class testscheduledthreadpoolexecutor {public static void main(string [] args){scheduledthreadpoolexecutor exec = new ScheduleDthreadPoolexecutor(1); exec.scheduleatfixedrate(new runnable(){//例外は時々@Override publicVoid run(){// new runtimeexcection(); System.out.println( "=============================================================================================================== =========================================================================================== =========================================================================================== =========================================================================================== timeUnit.milliseconds)出力結果:
================== 838464454951683864382903483888643830710 ================= 839064385138383926383879319840060063399383
上記はこの記事に関するものです。すべての人の学習に役立つことを願っています。