これに先立ち、私たちはスレッドの基本的な知識を持って、今日、このスレッドプールの技術をお届けします。私はより多くのJava関連の知識を習得するために公共の「サイドJavaコード」の数が心配です。
なぜ、スレッドプールを使用できますか?仕事をするために、スレッドプールは、実行中のスレッドの数を制御することが主な理由です。
スレッドプールの種類
Javaでの一般的なスレッドプール、4つがあります。newCachedThreadPool、newFixedThreadPool、newScheduledThreadPool、newSingleThreadExecutor。
newCachedThreadPool
役割は:スレッドプールの長さは、処理ニーズを超えた場合、アイドル状態のスレッド(回復する柔軟性キャッシュできるスレッドプールを作成し缓存中已有 60 秒钟未被使用的线程
)、そうでない場合は回収し、新しいスレッドを。
特長:スレッドプールが無限大である2番目のタスク、最初のタスクを実行するために使用するスレッドではなく、それぞれの時間よりも、新しいスレッドに複雑になるとき、最初のタスクが完了しました。
実現:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(index);
}
});
}
newFixedThreadPool
役割:固定サイズのスレッドプールを作成するために、あなたは同時スレッドの最大数を制御することができ、余分なスレッドは、キュー内で待機します。
特徴:
- 何らかのスレッドが終了するの故障に閉鎖する前に、実行中の場合は、(必要な場合)、後続のタスクを実行するために新しいスレッドと交換してください。
- スレッドが明示的に閉じられる前に、スレッドプールは常に存在します。
定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。
実現:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
newScheduledThreadPool
役割:定期的かつ定期的なタスクの実行をサポートするために、固定長のスレッドプールを作成します。
実現:
ScheduledExecutorService scheduledThreadPoo l= Executors.newScheduledThreadPool(3);
scheduledThreadPool.schedule(newRunnable() {
@Override
public void run() {
System.out.println("延迟三秒");
}
}, 3, TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(newRunnable(){
@Override
public void run() {
System.out.println("延迟 1 秒后每三秒执行一次");
}
}, 1, 3, TimeUnit.SECONDS);
newSingleThreadExecutor
役割:すべてのタスクが指定された順(FIFO、LIFO、優先順位)で実行されることを保証するタスクのみワーカースレッドを実行するためにのみ使用し、シングルスレッドのスレッドプールを作成します。
特徴:(または例外が発生したとき)は、スレッドの死の後に再起動することができますスレッドプールのスレッドで実行を継続するために元のスレッドを交換します。
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
原理スレッドプール
役割:スレッドの多重化、同時の最大数を制御し、スレッド管理を。仕事をするために、スレッドプールは、実行中のスレッドの数を制御することが主で、タスクはキュー・プロセスに置かれ、その後、スレッドの作成後にこれらのタスクを開始し、スレッドの数が超えた場合、最大数はラインで待っているスレッド数を超えると、実行の他のスレッドされます完成した後、タスクを実行するためにキューから取得されます。
スレッドの多重化
それぞれのThreadクラスのstart()メソッドを持っています。あなたは、開始スレッドのJava仮想マシンを起動する呼び出すと、実行クラス()メソッドを呼び出します。そして、クラスのrun()メソッドは、run()メソッドRunnableオブジェクトを呼び出すことです。私たちは、Runnableオブジェクトの呼び出しがその開始()メソッドに渡され、サイクルを追加し続け、Threadクラスを継承書き換えることができます。これは、スレッドプールの原則の実現です。Runnableをキューへの連続アクセスを有するサイクリックプロセスは次のRunnableがブロックされていてもよい得る前に、実現されます。
スレッドプールの構成
一般的なスレッドプールは、次の4つのコンポーネントに分割されています。
- プールマネージャスレッド:スレッドプールを作成して管理します。
- ワーカースレッド:プール内のスレッド。
- タスク・インタフェース:各タスクの実行スケジュールワーカースレッドのためのインタフェースを実装する必要があります。
- タスクキュー:バッファリング機構を提供するために処理するタスクを記憶するための手段。
プール内のJavaスレッドはエグゼキュータフレームワークによって実現され、我々は執行、エグゼキュータ、ExecutorServiceの、ThreadPoolExecutor、呼び出し可能と未来、FutureTask枠組みの中でこれらのクラスを使用していました。ThreadPoolExecutorの設定を次のように
/**
* @param corePoolSize 指定线程池中的线程数量
* @param maximumPoolSize 指定线程池中的最大线程数量
* @param keepAliveTime 当前线程池数量超过 corePoolSize 时,多余的空闲线程的存活时间
* @param unit keepAliveTime 的单位
* @param workQueue 任务队列,被提交但尚未被执行的任务
*/
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
// threadFactory 线程工厂,用于创建线程,一般用默认的即可
// handler 拒绝策略,当任务太多来不及处理,如何拒绝任务
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);
}
拒否ポリシー
役割:プール内のスレッドは、最大使用され、新しいタスクは、キューを待って新しいタスクを合わないだろう決して、すでに満杯である一方で、提供し続けることができません。今回は、この問題に対処するための合理的なメカニズムの政策を拒否する必要があります。
次のようにJDKの内蔵拒否戦略があります:
- AbortPolicy:通常の予防直接スロー、。
- CallerRunsPolicy:スレッドプールが閉じていない限りは、長い間、呼び出し側のスレッドで直接政策は、現在のタスクが破棄されて実行されます。明らかにこれは実際にタスクを破棄していない、しかし、ジョブ投入スレッドの性能が急激に低下する可能性があります。
- DiscardOldestPolicy:タスクが実行される最も古い要求を破棄し、現在のジョブを再送信してみてください。
- DiscardPolicy:このポリシーは、任意の処理をせず、黙って破棄されたタスクを処理することはできません。タスクが欠落している許可した場合、それはプログラムの最高の一種です。
その他の組み込みの拒否戦略は、上記の戦略は、まだ実際のニーズを満たすことができないならば、あなたは自分自身のRejectedExecutionHandlerのインターフェイスを拡張することができ、のRejectedExecutionHandlerのインターフェイスを達成しています。
Javaスレッドプールのワーカープロセス
- スレッドプールを作成した場合は、どのスレッドがありません。タスクキューは、パラメータとして渡されます。しかし、仕事を持っているキュー場合は、スレッドプールは、それらをすぐに実行されません。
- タスクを追加するためにexecute()メソッドを呼び出すと、スレッド・プールには、次のような判断を行います。
a)の場合は、すぐにこのタスクを実行するスレッドを作成し、以下corePoolSizeよりも実行しているスレッドの数。
B)もしスレッド以上corePoolSize、キューにこのタスクを実行するの数。
c)は、この時間は、キューがいっぱいになって、実行中のスレッドの数が少ないmaximumPoolSizeよりも、あなたはまだする必要がある場合は
すぐにこのタスクを実行するために、非コアスレッドを作成します。
キューがいっぱいになると、スレッドの数がより多いを実行しているか、maximumPoolSizeに等しい場合はD)、スレッドプールは例外RejectExecutionExceptionがスローされます。
- スレッドがタスクを完了するためにある場合には、タスクを実行するためにキューから削除されます。
- スレッドは何もより一定期間(keepAliveTimeが)よりもされていない場合、スレッドプールは、現在実行中のスレッドの数がcorePoolSize以上である場合、スレッドは停止されるかを決定します。スレッドプールのすべてのタスクが完了した後だから、それは最終的にcorePoolSizeのサイズに縮小します。
マルチスレッドと並行処理シリーズが推奨します
Javaのスレッドが予定されているかのスレッドコンテキストで何03--、マルチは、スレッド