1.スレッドプールの使用シナリオ
- 1つのタスクの処理時間が短い
- 処理される多数のタスク
第二に、Javaスレッドプールを使用する利点
1.新しいスレッド()を使用してスレッドを作成することの欠点:
- 毎回新しいThread()を使用してオブジェクトを作成するパフォーマンスは良くありません。
- スレッドの統一された管理の欠如は、無制限のスレッドを作成し、互いに競合し、クラッシュまたはoomを引き起こすにはシステムリソースを多く占有する可能性があります。
- 定期的な実行、定期的な実行、スレッドの中断など、より多くの機能の欠如。
2. Javaスレッドプールを使用する利点:
- 既存のスレッドを再利用し、オブジェクトの作成と消滅のコストを削減し、パフォーマンスを向上させます。
- 同時スレッドの最大数を効果的に制御し、システムリソースの使用率を向上させ、過剰なリソースの競合を回避し、輻輳を回避できます。
- 定期的実行、定期的実行、単一スレッド、同時数制御およびその他の機能を提供します。
Java 4スレッドプール
JavaのスレッドプールのトップインターフェースはExecutorですが、厳密に言うと、Executorはスレッドプールではなく、スレッドを実行するためのツールにすぎません。実際のスレッドプールインターフェイスはExecutorServiceです。次の図は、スレッドプールクラスのアーキテクチャを完全に説明しています。
1. newCachedThreadPool
は、必要に応じて新しいスレッドを作成できるスレッドプールを作成しますが、以前に構築されたスレッドが利用可能になると、それらを再利用します。多くの短期非同期タスクを実行するプログラムの場合、これらのスレッドプールはプログラムのパフォーマンスを向上させることができます。executeを呼び出すと、以前に構築されたスレッドが再利用されます(スレッドが使用可能な場合)。利用可能な既存のスレッドがない場合、新しいスレッドが作成され、プールに追加されます。60秒間使用されなかったスレッドを終了して削除します。したがって、長時間アイドル状態にあるスレッドプールはリソースを使用しません。
public static ExecutorService newCachedThreadPool()の
コード例:
public class ThreadPoolExecutorTest {
public static void main(String[] args ) {
ExecutorService cacheThreadPool =Executors.newCachedThreadPool();
for(int i =1;i<=5;i++){
final int index=i ;
try{
Thread.sleep(1000);
}catch(InterruptedException e ) {
e.printStackTrace();
}
cacheThreadPool.execute(new Runnable(){
@Override
public void run() {
System.out.println("第" +index +"个线程" +Thread.currentThread().getName());
}
});
}
}
}
//输出结果
第1个线程pool-1-thread-1
第2个线程pool-1-thread-1
第3个线程pool-1-thread-1
第4个线程pool-1-thread-1 第5个线程pool-1-thread-1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26日
- 27日
由结果可看出 当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
2. newFixedThreadPool
创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
public static ExecutorService newFixedThreadPool(int nThreads)
nThreads - 池中的线程数
示例代码:
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService fixedThreadPool =Executors. newFixedThreadPool(3);
for (int i =1; i<=5;i++){
final int index=i ;
fixedThreadPool.execute(new Runnable(){
@Override
public void run() {
try {
System.out.println("第" +index + "个线程" +Thread.currentThread().getName());
Thread.sleep(1000);
} catch(InterruptedException e ) {
e .printStackTrace();
}
}
});
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
由于设置最大线程数为3,所以在输出三个数后等待2秒后才继续输出。
2. newScheduledThreadPool
创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
corePoolSize - 池中所保存的线程数,即使线程是空闲的也包括在内。
延迟执行示例代码:
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);
scheduledThreadPool.schedule(newRunnable(){
@Override
public void run() {
System.out.println("延迟三秒");
}
}, 3, TimeUnit.SECONDS);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
表示延迟3秒执行。
定期执行示例代码:
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);
scheduledThreadPool.scheduleAtFixedRate(newRunnable(){
@Override
public void run() {
System.out.println("延迟1秒后每三秒执行一次");
}
},1,3,TimeUnit.SECONDS);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
表示延迟1秒后每3秒执行一次。
4. newSingleThreadExecutor
は、単一のワーカースレッドを使用して無制限のキューでスレッドを実行するエグゼキュータを作成します。(シャットダウン前の実行中にエラーが発生してこの単一のスレッドが終了した場合、新しいスレッドは、必要に応じて代わりに後続のタスクを実行します)。各タスクが順次実行されることが保証され、同時に複数のスレッドがアクティブになることはありません。他の同等のnewFixedThreadPool(1)とは異なり、このメソッドによって返されるエグゼキューターを再構成せずに他のスレッドを使用できることを保証できます。
パブリック静的ExecutorService newSingleThreadExecutor()
サンプルコード:
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService singleThreadPool= Executors.newSingleThreadExecutor();
for(int i=1;i<=5;i++){
int index=i;
singleThreadPool.execute(new Runnable(){
@Override
public void run() {
try{
System.out.println("第"+index+"个线程");
Thread.sleep(2000);
}catch(InterruptedException e) {
e.printStackTrace();
}
} });
}
}
}