Java 5から、Javaは独自のスレッドプールを提供します。スレッドプールはスレッドコンテナであり、一度に定格のスレッド数のみを実行します。 java.util.concurrent.threadpoolexecutorはそのようなスレッドプールです。非常に柔軟ですが、使用するのも複雑であるため、この記事で紹介します。
最初はコンストラクターです。最も単純なコンストラクターを例にとってください。
public threadpoolexecutor(int corepoolsize、int maximumpoolsize、long keepalivetime、timeunit unit、blockingqueue <runnable> workqueue)
非常に複雑に見えます。ここに紹介させてください。
CorePoolsizeは、予約されたスレッドプールサイズを指します。
Maximumpoolsizeとは、スレッドプールの最大サイズを指します。
KeepAlivetimeとは、アイドルスレッドが終了するタイムアウト時間を指します。
ユニットは、KeepAlivetimeの単位を表す列挙です。
Workqueueは、タスクを保存するためのキューを表します。
スレッドプールの作業プロセスからのこれらのパラメーターの重要性を理解できます。スレッドプールの作業プロセスは次のとおりです。
1.スレッドプールが最初に作成されたとき、内部のスレッドはありませんでした。タスクキューはパラメーターとして渡されます。ただし、キューにタスクがある場合でも、スレッドプールはすぐに実行されません。
2。execute()メソッドを呼び出してタスクを追加すると、スレッドプールは次の判断を下します。
a。
bランニングスレッドの数がCorePoolsize以上である場合、このタスクをキューに入れます。
C。
dキューがいっぱいで、実行されているスレッドの数がMaximumumpoolsize以上である場合、スレッドプールは「タスクを受け入れることはできません」という例外をスローします。
3.スレッドがタスクを完了すると、キューからタスクが実行されます。
4.スレッドには何の関係もなく、一定の時間(KeepAlivetime)が必要な場合、スレッドプールは、現在実行されているスレッドの数がCorePoolsizeよりも大きい場合、スレッドは停止すると判断します。したがって、スレッドプールのすべてのタスクが完了した後、最終的にCorePoolsizeのサイズに縮小します。
このプロセスは、最初にタスクに参加する場合、最初にタスクを実行する必要がないことを示しています。キューサイズが10、corepoolsizeは3、maximummumpoolsizeは6であると仮定すると、20のタスクが追加されると、実行順序は次のとおりです。最初に、タスク1、2、3が実行され、タスク4〜13が配置されます。キューで。この時点で、キューはいっぱいで、タスク14、15、16はすぐに実行され、タスク17〜20は例外をスローします。最終順序は次のとおりです。1、2、3、14、15、16、4、5、6、7、8、9、10、11、12、13。スレッドプールの使用の例は次のとおりです。
public static void main(string [] args){blockingqueue <runnable> queue = new linkedblockingquutor <runnable>(); 0; i <20; out println( "this.hashcode())}};
この例の説明は次のとおりです。
1。ブロッキングキューは単なるインターフェースです。 LinkedBlockingQueueを使用する利点は、サイズ制限がないことです。このように、キューがいっぱいにならないため、execute()は例外をスローしません。スレッドプールで実行されるスレッドの数はCorePoolsizeを超えることはないため、KeepAlivetimeパラメーターは無意味です。
2。Shutdown()メソッドはブロックされません。 Shutdown()メソッドを呼び出した後、メインスレッドはすぐに終了し、スレッドプールは停止する前にすべてのタスクが実行されるまで実行され続けます。 Shutdown()メソッドが呼び出されない場合、スレッドプールは残り、新しいタスクをいつでも追加できるようにします。
この時点で、私はこのスレッドプールのごく一部を導入しました。 ThreadPoolexecutorは非常にスケーラブルですが、それを拡張するという前提は、それがどのように機能するかに精通することです。次の記事では、ThreadPoolExecutorクラスを拡張する方法について説明します。
ava.util.concurrent.threadpoolexecutorクラスは、豊富な拡張性を提供します。サブクラスを作成して、動作をカスタマイズできます。たとえば、各タスクが終了した後にメッセージを印刷したいのですが、タスクオブジェクトを変更することはできません。これを書くことができます。
ThreadPoolexecutor executor = new SthreadPoolexecutor(Size、Maxsize、1、TimeUnit.days、Queue)
afterexecuteメソッドに加えて、threadpoolexecutorクラスには、タスクが実行される前に実行され、スレッドプール全体が停止した後に実行される有効化できるExexecute()およびExermated()メソッドの前にもあります。
タスクが実行される前後のアクションを追加することに加えて、ThreadPoolexecutorを使用すると、タスクが失敗した後に実行ポリシーをカスタマイズすることもできます。スレッドプールのsetRejectedExecutionHandler()メソッドを呼び出し、既存のポリシーをカスタム拒否ExecutionHandlerオブジェクトに置き換えることができます。 ThreadPoolexecutorは、4つの既存のポリシーを提供します。
threadPoolexecutor.abortPolicy:タスクが拒否され、例外がスローされていることを示します
threadPoolexecutor.DiscardPolicy:タスクを拒否するが、アクションを実行しないことを意味します
SthreadPoolexecutor.CallerrunSpolicy:タスクが拒否され、タスクが発信者のスレッドで直接実行されることを示します。
SthreadPoolexecutor.DiscardOldESTPolicy:タスクキューの最初のタスクが最初に破棄され、次にタスクがキューに追加されることを意味します。
これが例です:
SthreadPoolexecutor executor = new ThreadPoolexecutor(size、maxsize、1、timeunit.days、queue);
executor.setRejectedExecutionHandler(new ThreadPoolexecutor.DiscardPolicy());
さらに、拒否ExecutionHandlerインターフェイスを実装することにより、独自のポリシーを作成することもできます。これが例です:
swerchpoolexecutor executor = new ThreadPoolexecutor(3、6、1、TimeUnit.Seconds、Queue、new RejectedExecutionHandler(){public void reljectedexecuti on(runnable r、threadpoolexecutor executor){system.out.println(string.format( "exc%d rejected d rejected d rejected d -rejected) 。