ThreadPoolExecutorを達成するためのスレッドプール

まず、スレッドプールを使用する目的

適切に管理されないスレッドが簡単にシステムの問題につながることができれば、実際の使用では、スレッドは、システムリソースを占有しています。そのため、スレッドプールは、同時実行スレッドを管理するために、ほとんどのフレームワークで使用されます。スレッドプールのスレッド管理は、主に次のような利点を持って使用します。

リソースの消費を低減する1:スレッドを多重化することにより、可能な限りシステム損失を低減し、閉じて、既存のスレッドの数を減少させます。

2、システムの応答が提供され、スレッドを多重化することにより、スレッド作成処理を省略し、従って、システムの全体的な応答速度を向上されています。

図3は、スレッドの管理性を向上させる:スレッドが希少資源である、無限の創造場合、システムリソースを消費するだけでなく、したがって、スレッドを管理するスレッドプールを使用する必要がシステムの安定性を減らします。

第二に、スレッドプールの構成

一般的に、単純なスレッドは、少なくとも以下のコンポーネントがあります。

図1に示すように、スレッドマネージャ(ThreadPoolManager):スレッドプールを作成および管理するために使用されます。

図2に示すように、ワーカースレッド(workThread):スレッドプールスレッド。

3、タスクインターフェイス(タスク):各タスクは、スレッドスケジューリングタスクの実装のため、実装する必要があります。

図4に示すように、タスクキュー:タスクを格納するために、処理されない緩衝機構を提供します。

スレッドプールマネージャは、少なくとも以下の機能を備えています。スレッドプールを作成し、新しいタスクを追加し、スレッドプールの破壊をスレッドプールを作成します。図は次のとおりです。

第三に、スレッドプールの構成

同時タスクは、スレッドプールを提出した場合、スレッドプールのスレッドは図の手順に示されているタスクに割り当てられます。

図からわかるように、メインが提出したその任務を実行するためのスレッドプールは、いくつかの段階があります。

1、最初のスレッド・プールの核決定心臓スレッドプールをすべてのスレッドがすべてではない場合は、手順2に進み、スレッドプール内のすべてのスレッドは、コアミッションであり、そうでない場合は、単に提出タスクを実行するためのスレッドを作成して、ミッションにあります;

2は、現在のかどうかを決定するブロッキングキューはステップ3へ行くには、フルではない場合、タスクは、ブロッキングキューの代わりに提出されるだろう、満杯ではありません。

図3は、決定したスレッド・プール内のすべてのスレッドをミッションにしている場合ではない場合は、タスクを実行する新しいスレッドを作成し、または処理のための飽和戦略へ。

第四に、スレッドプールを作成します

主にあるスレッドプールを作成します。ThreadPoolExecutorの完全にクラス、引数のコンストラクタスレッドプールのほとんどは、これらのパラメータは、特に設定する必要があります理解するためにそこを通って過負荷にThreadPoolExecutor多くの方法が、あります。

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

次のパラメータについて説明します。

1、corePoolSizeは:スレッドプールのサイズを示し、ジョブを送信する際に、糸の強力なコア数のプールがcorePoolSizeに達していない場合、新しいスレッドは、提出されたタスクを実行するために作成されている場合や、現在のコアスレッドプールがフリー有する場合であってもスレッドは、スレッドプール内のスレッドの現在の数は、コアcorePoolSizeに達した場合は呼び出した場合、もはや、スレッドを作成していないprestartCoreThread()か、 prestartAllCoreThreads()それらが作成され、開始されたとき、コア、スレッドプールのスレッドの全てが作成されます。

2、maximumPoolSizeは:スレッドプールは、スレッドの最大数を作成することができることを示しています。キューがいっぱいになると、スレッドプールの現在の数がmaxmumPoolSizeを超えない場合にブロックされた場合は、タスクを実行するために、新しいスレッドを作成します。

図3は、keepAliveTimeがアイドルスレッドの生存時間は、このような過電流プールとしてはCorePoolSizeスレッドの数を超えていると、それは、システムリソースの消費を低減するように、スレッドが破壊されるアイドルになるスレッドがKeepAliveTimeのよりアイドル状態です。

図4に示すように、単位時間の単位は、時間の単位を指定keepAliveTimeがあります。

図5に示すように、ワークキュー:ブロッキングキューは、タスクキューのブロックを格納するための、ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、priorityBlockingQueue使用することができます。

6、ThreadFactory:もっと意味のある名前を作成するために着手したスレッドごとに指定することにより、エンジニアリングスレッド、スレッドファクトリを作成します。問題が発生した場合は、だけでなく、簡単な問題の原因を見つけるために。

図7は、ハンドラ:飽和戦略は、スレッド・プールがいっぱいで、指定されたスレッドが現在のスレッド・プールがすでに飽和していることを示す、開かれている時にキューをブロックし、その後、我々は戦略を使用して、このような状況に対処するための戦略を採用する必要がありますこれらのタイプ:

  • AbortPolicy:直接拒否タスク提出とRejectedExecutionException例外を投げます。
  • CallerRunsPolicy:場合にのみスレッド呼び出し側でタスクを実行します。
  • DiscardPolicy:直接失うタスクを扱いません。
  • DiscardOldestPolicy:現在のタスクのブロッキングキュー記憶最長のタスクの実行を捨てます。

ThreadPoolExecutorのメソッド実行ロジックをコメントを参照してください実行。ThreadPoolExecutorの実行方法を示す以下の模式図を行います。

Executeメソッドの実行ロジックは、いくつかの状況があります。

1、現在実行中のスレッド少ないとcorePoolSizeあれば、それは新しいタスクを実行する新しいスレッドを作成します。

スレッドの実行数がcorePoolSize以上である場合、図2に示すように、タスクは、ワークキューに格納されているブロッキングキューに提出されます。

3現在のワークキューキューがいっぱいの場合、これはタスクを実行するために、新しいスレッドを作成します。

スレッドの数がmaximunPoolSizeを超えた場合、図4に示すように、飽和戦略のRejectedExecutionHandlerで処理されます。

コアスレッドプールCorePoolSize、スレッドプールやブロックキューワークキューmaxmumPoolSize、タスクを処理するために、このキャッシュ戦略を使用することであるスレッドプールの設計は、この設計は、多くのフレームワークで使用されることに留意すべきです。

第五に、スレッドプールが閉鎖されます

閉じるスレッドプール、することができますシャットダウンし、shutdownNowのこれらの2つの方法。その原理は、割り込みスレッドが続き、プール内のスレッドの全てを横断することです。次のように両方の違いは次のとおりです。

図1に示すように、スレッドプールのshutdownNowの最初の状態が停止するように設定し、すべてのスレッドが実行し、実行していない停止しようとしています。そして、実行を待っているタスクのリストを返します。

2、スレッドプールの状態がシャットダウン状態に設定され、実行のすべてのスレッドを中断されていないことを除いて、シャットダウン。

見ることができるようにタスクが停止方法は、完全な実装していきます実行されている、とshutdownNowの直接割り込みタスクが実行されています。真のメソッドが返すisshutdwonこれらの2つの方法のいずれか、すべてのスレッドが正常に閉じているとき、それはスレッドプールが閉じていることを示すを呼び出します。これは、メソッドの呼び出しが戻る真isTerminatedの意志です。

第六に、どのように適切にスレッドプールのパラメータを設定するには

スレッドプールの合理的な配分に、あなたが最初のタスクの特性を分析する必要があり、次のような視点から分析することができます。

1、タスクの性質:CPU集約型タスク、IO集中型のタスクとの混合作業;

2、タスクの優先度:高、低、中

3、タスクの実行時間:ロング、セミロング、ショート

図4に示すように、タスク依存:もしそのようなデータベース接続のような他のシステムリソースに依存。

公開された21元の記事 ウォンの賞賛4 ビュー503

おすすめ

転載: blog.csdn.net/weixin_39617728/article/details/105019782