[並行プログラミング - ファンデーション](VIII)スレッドプール

記事のディレクトリ

A、新しいスレッドの欠点

  • たびに新しいスレッド新しいオブジェクト、パフォーマンスの低下。
  • (だけでなく、別の新しいスレッドので、新しいスレッドをトリガするために引き続き、設計に欠陥があるかもしれません)一元管理の欠如、無限の可能性新しいスレッド、互いに競合するスレッド、それはあまりにも多くのシステムリソースを占有することが可能であることは、死亡またはOOMにつながる可能性があります。
  • そのようなより多くの定期的な実行スレッドの割り込みの実装として、より多くの機能を欠いています。

第二に、スレッドプールのメリット

  • 既存のスレッド再利用し、常にオブジェクトの作成、コストの終焉、良好なパフォーマンスを減らし、スレッドを作成しないでください。
  • これは、効果的にシステムリソースの使用率を向上させること、同時スレッドの最大数を制御し、資源、回避を阻止するための過当競争を避けることができます
  • タイミングは定期的に、シングルスレッド、同時制御機能を実行するために実行します

第三に、コアスレッドプールのクラス-ThreadPoolExecutor

3.1三つのパラメータ、スレッドプール

       3.1.1、corePoolSize(スレッドのコア数)
       3.1.2、maximumPoolSize(スレッドのスレッドの最大数)
       3.1.3、ワークキュー(待ち行列をブロックします)
  • 実行されるのを待っているタスクを格納するため、非常に重要な、スレッドプールに大きな影響を実行するプロセスであります
       3.1.4、keepAliveTimeが(長い時間の終了を実行するときに、スレッドがタスクにホールドアップされません)
       3.1.5、単位(時間のkeepAliveTimeがユニット)
       3.1.6、threadFactory(スレッドファクトリ)
  • スレッドを作成するには(デフォルトはスレッドを作成するために、デフォルトの工場を持っていますが、スレッドはデフォルトのファクトリを使用して作成され、新しく作成されたスレッドが同じ優先順位と非デーモンスレッドを持っているだけでなく、スレッドの名前を設定します)
       3.1.7、rejectHandler(拒否の戦略タスクの処理)

拒否ポリシーの処理の4種類

1、直接スロー例外(デフォルト)AbrotPolicy。

2、呼び出し側のスレッドでタスクCallerRunsPolicyを実行します。

図3は、キューから削除され、タスクに最も順方向電流のタスクDiscardOldstPolicyを実行します。

4、タスクDisccardPolicyを破棄

3.2スレッドプールの作業、ジョブ投入

       3.2.1、ジョブ投入のタスクを処理するためのスレッドプールとの間の関係のパラメータ
  • スレッドの数がcorePoolSizeよりも少ないを実行している場合は、直接プール内の他のスレッドがアイドル状態であっても、タスクを処理する新しいスレッドを作成します。
  • もしスレッドプールの大きい内のスレッドの数よりも少ない値corePoolSize値それがタスクを処理するための新しいスレッドを作成している唯一のワークキューフルmaximunPoolSizeに等しいより。
  • corePoolSizeとmaximumPoolSizeが同じ場合は、新しいユーザーの提出がある場合は、この時間をプールのサイズが固定されているスレッドを作成し、ワークキューは、空きスレッドを待って、ワークキューの内側にフルタイムにリクエストを入れ、その後、内部のワークキューからではありませんタスクを削除します。
  • スレッドの数はmaximumpoolSizeより大きいを実行している場合はワークキューが満杯だった場合、それは背中の導入によって、このタスクに対処することを拒否するためのポリシーのポリシーのパラメータを指定します。
  • タスクが送信されるときに、三つの主要な順序があり、最初はcorePoolSizeで、それが直接スレッドとコールを作成するよりも少ないです。次は最後のmaximumuPoolSizeで、ワークキューです。
       3.2.2、新しいジョブ3つの処理モードスレッドプールを提出
  • スレッドプールは、現在のモードを実行しているタスク処理スレッドプールスレッドの数に応じて決定されます後にワークキューは、我々は、スレッドプールに新しいタスクを送信すると、タスク実行待ちのブロッキングキューを保持することで、3回の治療があります
(1)直接スイッチング(SynchronusQueue)
(2)非有界キュー(LinkedBlockingQueue)の使用
  • corePoolSizeのために作成できるスレッドの最大数は、その後、maximumPoolSizeが役割を果たしています。
  • すべてのコアスレッドプールのスレッドが状態を実行している場合は、新しいミッションは、待機キューにサブミットされます。
(3)有界キュー(ArrayBlockingQueue付き)
  • 最大maximumPoolSizeは、資源の消費を減らすが、スレッドプールのスレッドのスケジューリングがより困難になるようすることができます。
  • スレッドプールおよびキューの容量が限られているため。だから、スループットせて、合理的な範囲にスレッドプールのタスクを処理して、我々は、スレッドのスケジューリングが比較的単純であることを確認するために、また、資源の消費を最小限に抑えたい、我々は合理的な制限の両方の番号が必要です。

3.3スレッドプール割当技術

  • CPU使用率を低減含むリソースの消費を低減するために、オペレーティング・システムの消費リソースオーバーヘッドコンテキスト切り替え等は、大小スレッドキュー容量プール容量を提供することができる、これは、スレッドプールのスループットを低下させます。
  • 私たちが提出したタスクは、多くの場合、目詰まりした場合、我々はmaximumPoolSizeを調整することができます。私たちのキューの容量が小さい場合には、CPUの使用率が比較的高くなりますので、我々は、より大きなスレッドプールのサイズを設定する必要があります。
  • スレッドプールの容量が大きすぎる設定されている場合、並行処理の量が増加するが、その後、スレッド間のスケジューリング問題を考慮する必要があるときしかし、あまりにも多くのタスクが向上します。しかし、これは、処理タスクのスループットを低下させることができます。

第四に、状態のスレッドインスタンス

  • これらの状態は、これらの治療を行うための内部スレッドプールで、対処しません。

4.1、RUNNING

       あなたは、提出と処理タスクがキューにブロックすることができる新しいタスクを受け取ることができます。

4.2、SHUTDOWN

       それは時にSHUTDOWN状態のスレッド・プールのインスタンスの新しいタスクを受け入れるもはや言及しないように、閉じた状態に属している、唯一のブロッキングキュー記憶されているジョブを処理し続けることができます。スレッドプールは、RUNNING状態にある場合には、スレッド・プールがこの状態に入ります、シャットダウン()メソッドを呼び出します。

4.3、STOP

       スレッドプールを使用すると、shutdownNowの()メソッドを呼び出した場合、スレッドプールは、状態に入りますRUNNINGまたはSHUTDOWN状態にあるときは、新しいタスクを受け入れないでください、タスクキューを処理しない、中断されたスレッドがタスクを処理しています。

4.4、片付け

       すべてのタスクが終了しているが、この時間は、アクティブなスレッドの数が0の場合、コールは、TERMINATED状態になり、デフォルトは終了()メソッドを終了した後、スレッドプールメソッドは何もしません()、状態に入ります、ちょうど最後の状態を入力してください。

4.5、TERMINATED

       最終状態。

第五に、この方法は、ThreadPoolExecutorを提供しました

5.1基本的な方法:

  • 実行():スレッドプールを実行するためのタスクを提出
  • 提出():タスクを提出します。+今後の実行の結果を返すために、
  • シャットダウン():クローズスレッドプールは、待機中のタスクが実行されます。システムリソースを節約するためにスレッドプールを閉じます
  • shutdownNowの():近いタスクの実行完了を待たずにスレッドプールは、スレッドの実行を一時停止します。すべてのタスクを中断しなければならなかったために適用され、これはまれです。

5.2監視方法:

  • getTaskCount():スレッドプールタスクの総数が実行され、未実行されています
  • getCompletedTaskCount():完了したタスクの数
  • getPoolSize():スレッド内のスレッドの現在の数
  • getActiveCount():スレッドプール内のスレッドの現在の数は、タスクを実行しています

5.3、図3の方法。

       

六、エグゼキュータ・フレームワーク・インタフェースおよび一般的な方法

6.1、エグゼキュータスレッドプールのクラス図

ここに画像を挿入説明

6.2、Exector 4つのインターフェイスの決意

       6.2.1、エグゼキュータ
  • エグゼキュータは、新しいタスクを実行するためのシンプルなインターフェイスです。
       6.2.2、ExecutorServiceの
  • ExecutorServiceのアクチュエータとミッションライフサイクルのライフサイクルを管理する方法の数を加算し、エグゼキュータインタフェースを拡張します。
       6.2.3、ScheduledExecutorService
  • ScheduledExecutorServiceは今後と定期的なタスクをサポートExecutorServiceのメソッドを拡張しました
       6.2.4、ThreadPoolExecutor
  • ThreadPoolExecutorは、私たち自身のニーズに応じているので、関数内で最強の図であり、彼は最初だけにして話すを置いて、我々は、任意のポリシーを指定するためのパラメータを渡す必要があります

6.3、エグゼキュータ4つのスレッドプールを作成します

       6.3.1、newCachedThreadPool(キャッシュされたスレッド・プールを作成します)
  • Executors.newCachedThreadPool:创建的是一个可缓存的线程池,如果线程池长度,超过了处理的需要,可以灵活回收空闲线程,如果没有可以回收的,就新建线程。
       6.3.2、newFixedThreadPool(创建定长的线程池)
  • Executors.newFixedThreadPool:创建的是一个定长的线程池,可以控制线程的最大并发数,超出的线程会在队列中等待。
       6.3.3、newScheduledThreadPool(定长的线程池,支持定时以及周期性的任务)
  • Executors.newScheduledThreadPool:创建的也是一个定长的线程池,支持定时以及周期性的任务。
       6.3.4、newSingleThreadExecutor(创建单线程化的线程池)
  • Executors.newSingleThreadExecutor:创建的是一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序去执行,可以按照先入先出,优先级等等去执行。

七、合理配置线程池

7.1、配置线程池原则

  • CPU密集型任务,就需要尽量压榨CPU,参考值可以设为NCPU+1

  • IO密集型任务,参考值可以设置为2*NCPU

  • 可以先将线程池大小设置为参考值,再观察任务运行情况,系统负载,资源利用率等等来进行适当调整。

7.2、配置线程池需注意

  • 使用线程池主要是为了同用存在的线程,减少对象创建消亡,能有效的控制并发线程数,可以避免过多的资源竞争,避免阻塞,也可以定时执行,单线程等控制性能的执行,性能比较好。当然不代表要随时随地的拿出线程池来用,一定要根据自己的实际场景来分析使用,以及参数配置。
  • 有时候用线程池没有直接进行来的快:当线程池里面的任务数很小时,小到任务进行的时间与任务调度的时间很接近的时候,这时候用线程池,反而会格外慢,因为花在任务调度和任务管理的时间就会更多。
公開された20元の記事 ウォンの賞賛1 ビュー559

おすすめ

転載: blog.csdn.net/weixin_42295814/article/details/103792458