ホームページ  >  記事  >  Java  >  Java のスレッド プールの動作特性を例とともに紹介します

Java のスレッド プールの動作特性を例とともに紹介します

高洛峰
高洛峰オリジナル
2017-02-07 15:01:101427ブラウズ

スレッドプールを使用しなければならない理由は何ですか?

個人的には、主な理由は次のとおりだと思います: 短期間に処理する必要があるタスクの数:

スレッド プールを使用する利点:

1. スレッドの作成と破棄にかかる時間を削減します。システム リソースのオーバーヘッド
2. スレッド プールを使用すると、システムが大量のスレッドを作成し、すべてのシステム メモリを消費する可能性があります。次に、Java に付属するいくつかのスレッド プールを示します。指定された数のワーカー スレッドを含むスレッド プール。

ワーカースレッドの数がスレッドプールの初期最大数に達すると、タスクが送信されるたびにワーカースレッドが作成され、送信されたタスクはプールキューに格納されます。

2. newCachedThreadPool はキャッシュ可能なスレッド プールを作成します。

このタイプのスレッド プールの特徴は次のとおりです:

1) 作成されるワーカー スレッドの数にはほとんど制限がありません (実際には制限があり、その数は整数 MAX_VALUE です)。スレッドプールに柔軟に追加できます。

2) スレッド プールにタスクが長期間送信されない場合、つまり、ワーカー スレッドが指定された時間 (デフォルトは 1 分) アイドル状態である場合、ワーカー スレッドは自動的に終了します。終了後に新しいタスクを送信すると、スレッド プールはワーカー スレッドを再作成します。

3. newSingleThreadExecutor はシングルスレッドの Executor を作成します。つまり、タスクを実行するための固有のワーカー スレッドのみを作成します。このスレッドが異常終了した場合は、別のスレッドが代わりに実行されます (これがその特徴だと思います)。

単一ワーカー スレッドの最大の特徴は、さまざまなタスクの順次実行を保証でき、常に複数のスレッドがアクティブになることがないことです。

4. newScheduleThreadPool は固定長のスレッド プールを作成し、タイマーと同様にスケジュールされた定期的なタスクの実行をサポートします。

概要:

1.FixedThreadPool は典型的な優れたスレッド プールであり、プログラムの効率を向上させ、スレッドの作成時に費やされるオーバーヘッドを節約するという利点があります。ただし、スレッド プールがアイドル状態のとき、つまりスレッド プールに実行可能なタスクがないときは、ワーカー スレッドは解放されず、特定のシステム リソースも占有します。

2. CachedThreadPool の特徴は、スレッド プールがアイドル状態のとき、つまりスレッド プールに実行可能なタスクがないときにワーカー スレッドを解放し、それによってワーカー スレッドが占有していたリソースを解放することです。ただし、新しいタスクが表示されると、新しいワーカー スレッドを作成する必要があり、ある程度のシステム オーバーヘッドが必要になります。また、CachedThreadPool を使用する場合は、タスクの数の制御に注意する必要があります。そうしないと、同時に多数のスレッドが実行されるため、システムが麻痺する可能性があります。

Java スレッド プール ThreadPoolExecutor の使用例

package com.sondon.mayi.jpool; 
  
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 
  
public class JPoolLearn { 
  
 private static int produceTaskSleepTime = 3; 
 private static int produceTaskMaxNumber = 20; 
   
 public void testThreadPoolExecutor(){ 
  /* 
   * ThreadPoolExecutor( 
   * int corePoolSize, //线程池维护线程的最少数量 
   * int maximumPoolSize, //线程池维护线程的最大数量 
   * long keepAliveTime, //线程池维护线程所允许的空闲时间 
   * TimeUnit unit, //线程池维护线程所允许的空闲时间的单位 
   * BlockingQueue<Runnable> workQueue, //线程池所使用的缓冲队列 
   * RejectedExecutionHandler handler //线程池对拒绝任务的处理策略 ) 
   */ 
  ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 
    5, 
    10, 
    3, 
    TimeUnit.SECONDS, 
    new ArrayBlockingQueue<Runnable>(10), 
    new ThreadPoolExecutor.DiscardOldestPolicy() 
    ); 
  
  for (int i = 1; i <= produceTaskMaxNumber; i++) { 
   try { 
    // 产生一个任务,并将其加入到线程池 
    String task = "task---" + i; 
    threadPool.execute(new ThreadPoolTask(task)); 
    System.out.println("activeCount :"+ threadPool.getActiveCount()); 
    // 便于观察,等待一段时间 
    Thread.sleep(produceTaskSleepTime); 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 
  } 
    
  //查看当前的线程池状况 
  while(true){ 
   try { 
    Thread.sleep(3000); 
    System.out.println("pool size :"+threadPool.getPoolSize());//线程池中线程数量 
    System.out.println("active count :"+threadPool.getActiveCount());//线程池中活动的线程数量 
   } catch (InterruptedException e) { 
    e.printStackTrace(); 
   } 
  } 
 } 
  
 /** 
  * 
  * @Author 蔡文锋 
  * @Data_Time 2015年7月25日 下午4:06:28 
  * @Description { 测试不同线程池模式 } 
  */ 
 public void testNewCachedThreadPool(){ 
  ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newCachedThreadPool(); 
//  ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newFixedThreadPool(100); 
//  ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newScheduledThreadPool(100); 
//  ThreadPoolExecutor threadPool=(ThreadPoolExecutor) Executors.newSingleThreadExecutor(); 
  try { 
  for (int i = 0; i < 100; i++) { 
   // 产生一个任务,并将其加入到线程池 
   String task = "task---" + i; 
   threadPool.execute(new ThreadPoolTask(task)); 
   System.out.println("activeCount :"); 
   // 便于观察,等待一段时间 
   Thread.sleep(produceTaskSleepTime); 
     
   } 
  } catch (InterruptedException e) { 
   e.printStackTrace(); 
  } 
  //查看当前的线程池状况 
  while(true){ 
   try { 
    Thread.sleep(3000); 
    System.out.println("pool size :"+threadPool.getPoolSize());//线程池中线程数量 
    System.out.println("active count :"+threadPool.getActiveCount());//线程池中活动的线程数量 
   } catch (InterruptedException e) { 
    e.printStackTrace(); 
   } 
  } 
 } 
   
 /** 
  * 
  * @Author 蔡文锋 
  * @Data_Time 2015年7月25日 下午4:06:58 
  * @Description { 测试callable与runable方法的区别 } 
  */ 
 public void testNewCachedThreadPool_callable(){ 
  ExecutorService es=Executors.newFixedThreadPool(10); 
  try { 
     
//   String result=es.submit(new MyCallable<String>()).get(); 
//   System.out.println("callable result :"+result); 
     
   String result=(String) es.submit(new ThreadPoolTask("")).get(); 
   System.out.println("runable result :"+result); 
     
  } catch (InterruptedException | ExecutionException e) { 
   e.printStackTrace(); 
  } 
 } 
   
   
 public static void main(String[] args) { 
  new JPoolLearn().testNewCachedThreadPool(); 
 } 
} 
  
  
  
/** 
 * 线程池执行的任务 
 */ 
class ThreadPoolTask implements Runnable { 
 private static int consumeTaskSleepTime = 2000; 
 // 保存任务所需要的数据 
 private Object threadPoolTaskData; 
  
 ThreadPoolTask(Object tasks) { 
  this.threadPoolTaskData = tasks; 
 } 
  
 public void run() { 
  System.out.println("start .." + threadPoolTaskData); 
  try { 
   // Sleep 2秒 模拟耗时操作 
   Thread.sleep(consumeTaskSleepTime); 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
  threadPoolTaskData = null; 
 } 
  
 public Object getTask() { 
  return this.threadPoolTaskData; 
 } 
} 
  
/** 
 * 
 * @Project : JPool 
 * @Package : com.sondon.mayi.jpool 
 * @Class : MyCallable 
 * @param <T> 
 */
class MyCallable<T> implements Callable<T>{ 
   
 @Override
 public T call() throws Exception { 
   System.out.println("开始执行Callable"); 
   return (T) "测试callable接口"; 
  } 
}

Java のスレッド プールの動作特性を紹介するその他の例については、PHP 中国語 Web サイトの関連記事に注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。