线程池类 ThreadPoolExecutor

                                              java 线程池ThreadPoolExecutor

一、线程池的作用
      1)降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
      2)提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
      3)提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

二、线程池ThreadPoolExecutor

   1.接口说明

  1. public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,  
  2.        BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);  
  各个参数的含义:

     corePoolSize:线程池维护线程的最少线程数,也是核心线程数,包括空闲线程。在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;

    maximumPoolSize: 线程池维护线程的最大线程数,它表示在线程池中最多能创建多少个线程;

    keepAliveTime: 线程池维护线程所允许的空闲时间.表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。

   unit: 线程池维护线程所允许的空闲时间的单位,keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:

            TimeUnit.DAYS;                                                 //天
            TimeUnit.HOURS;                                           //小时
            TimeUnit.MINUTES;                                       //分钟
            TimeUnit.SECONDS;                                    //秒
            TimeUnit.MILLISECONDS;                         //毫秒
            TimeUnit.MICROSECONDS;                    //微妙
            TimeUnit.NANOSECONDS;                    //纳秒

   workQueue:用于保存等待执行的任务的阻塞队列,阻塞队列有以下几种选择:
                         ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。 
                        LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。
                       SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于                                    LinkedBlockingQueue

  threadFactory:线程工厂,主要用来创建线程

  handler: 线程池对拒绝任务的处理策略 有以下四种取值:
                      ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 
                      ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。 
                      ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
                      ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 

   2.工作原理:

     任务通过execute(Runnable)方法添加到线程池,一个任务就是一个Runnable对象,任务的执行就是Runnable对象的run()方法.

      当一个任务将被添加到线程池中时:
               如果当前线程数小于corePoolSize,即使有空闲线程,也会创建新的线程来处理新增任务;
               如果当前线程数等于corePoolSize,如果缓冲队列未满,该任务被放入缓冲队列,池子里的空闲线程就去从workQueue中取任务并处理
               如果当前线程数大于corePoolSize,且冲队列已满,如果当前线程数小于maximumPoolSize, 就创建新的线程来处理新增任务;
               如果当前线程数等于maximumPoolSize,且冲队列已满,将会使用handler所指定的策略来处理任务.

    线程池处理任务的顺序是:
             核心线程corePoolSize,   缓冲队列workQueue,  最大线程maximumPoolSize
    当前线程数大于corePoolSize,线程池中的空闲线程在超过keepAliveTime, 会自动终止.线程池通过keepAliveTime来动态维护线程数.

3.代码

   

  1. import java.util.concurrent.ArrayBlockingQueue;  
  2. import java.util.concurrent.ThreadFactory;  
  3. import java.util.concurrent.ThreadPoolExecutor;  
  4. import java.util.concurrent.TimeUnit;  
  5. import java.util.concurrent.atomic.AtomicInteger;  
  6.   
  7. public class TestThreadPool {  
  8.       
  9.      public static void main(String[] args) {     
  10.          ThreadPoolExecutor executor = new ThreadPoolExecutor(2420, TimeUnit.MILLISECONDS,  
  11.                  new ArrayBlockingQueue<Runnable>(2),   
  12.                  new ThreadFactory() {  
  13.                      private AtomicInteger threadIndex = new AtomicInteger(0);  
  14.   
  15.                      @Override  
  16.                      public Thread newThread(Runnable r) {  
  17.                          return new Thread(r, "T" + this.threadIndex.incrementAndGet());  
  18.                      }  
  19.                  },  
  20.                  new ThreadPoolExecutor.DiscardOldestPolicy());  
  21.             
  22.          for(int i=0;i<9;i++){  
  23.              MyTask myTask = new MyTask(i);  
  24.              System.out.println("创建任务并提交到线程池中:任务" + i);    
  25.              executor.execute(myTask);  
  26.              System.out.println("线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+  
  27.              executor.getQueue().size()+",已执行玩别的任务数目:"+executor.getCompletedTaskCount());  
  28.          }  
  29.          executor.shutdown();  
  30.      }  
  31.   
  32. }  
  33.   
  34. class MyTask implements Runnable {  
  35.     private int taskNum;  
  36.        
  37.     public MyTask(int num) {  
  38.         this.taskNum = num;  
  39.     }  
  40.        
  41.     @Override  
  42.     public void run() {  
  43.         System.out.println("正在执行task "+taskNum+";Thread.currentThread().getName()="+Thread.currentThread().getName());  
  44.         try {  
  45.             Thread.currentThread().sleep(60000);  
  46.         } catch (InterruptedException e) {  
  47.             e.printStackTrace();  
  48.         }  
  49.         System.out.println("task "+taskNum+"执行完毕"+";Thread.currentThread().getName()="+Thread.currentThread().getName());  
  50.     }  
  51. }  

运行结果

 创建任务并提交到线程池中:任务0
正在执行task 0;Thread.currentThread().getName()=T1
线程池中线程数目:1,队列中等待执行的任务数目:0,已执行玩别的任务数目:0
创建任务并提交到线程池中:任务1
线程池中线程数目:2,队列中等待执行的任务数目:0,已执行玩别的任务数目:0
创建任务并提交到线程池中:任务2
正在执行task 1;Thread.currentThread().getName()=T2
线程池中线程数目:2,队列中等待执行的任务数目:1,已执行玩别的任务数目:0
创建任务并提交到线程池中:任务3
线程池中线程数目:2,队列中等待执行的任务数目:2,已执行玩别的任务数目:0
创建任务并提交到线程池中:任务4
线程池中线程数目:3,队列中等待执行的任务数目:2,已执行玩别的任务数目:0
创建任务并提交到线程池中:任务5
正在执行task 4;Thread.currentThread().getName()=T3
线程池中线程数目:4,队列中等待执行的任务数目:2,已执行玩别的任务数目:0
正在执行task 5;Thread.currentThread().getName()=T4
创建任务并提交到线程池中:任务6
线程池中线程数目:4,队列中等待执行的任务数目:2,已执行玩别的任务数目:0
创建任务并提交到线程池中:任务7
线程池中线程数目:4,队列中等待执行的任务数目:2,已执行玩别的任务数目:0
创建任务并提交到线程池中:任务8
线程池中线程数目:4,队列中等待执行的任务数目:2,已执行玩别的任务数目:0
task 0执行完毕;Thread.currentThread().getName()=T1
task 1执行完毕;Thread.currentThread().getName()=T2
正在执行task 7;Thread.currentThread().getName()=T1
正在执行task 8;Thread.currentThread().getName()=T2
task 5执行完毕;Thread.currentThread().getName()=T4
task 4执行完毕;Thread.currentThread().getName()=T3
task 7执行完毕;Thread.currentThread().getName()=T1
task 8执行完毕;Thread.currentThread().getName()=T2

原文:http://blog.csdn.net/lululove19870526/article/details/53283789

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
四种线程池ThreadPoolExecutor有着密切的关系。在Java中,通过Executors提供了四种线程池,这四种线程池底层都是由ThreadPoolExecutor实现的。ThreadPoolExecutor是一个灵活的线程池,可以根据需要进行配置和定制。通过掌握ThreadPoolExecutor的参数,我们可以不局限于四种线程池,而是根据实际需求构建自己的线程池。 其中,四种线程池分别是: 1. FixedThreadPool:固定大小的线程池,线程数固定,任务被放入一个无界队列中,适用于长期执行的任务。 2. CachedThreadPool:可缓存的线程池,线程数根据需求自动增加和减少,适用于执行大量短期任务的场景。 3. SingleThreadPool:单线程的线程池,只有一个线程在工作,适用于需要保证顺序执行的任务。 4. ScheduledThreadPool:定时任务的线程池,可以设置任务的定时执行时间。 ThreadPoolExecutor提供了更加灵活的线程池管理,可以通过设置不同的参数来控制线程池的行为。例如,可以选择不同的队列策略,如无界队列LinkedBlockingQueue,来控制线程池中任务的排队方式。通过学习和使用ThreadPoolExecutor,我们可以更好地理解和使用四种线程池,同时也可以根据实际需求进行自定义的线程池构建。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [JAVA线程池ThreadPoolExecutor实现的四种线程池](https://blog.csdn.net/a78270528/article/details/79881850)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Java ExecutorService四种线程池ThreadPoolExecutor机制](https://blog.csdn.net/Zzz_Zzz_Z/article/details/81218574)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值