线程池类 ThreadPoolExecutor

来源:互联网 发布:ff14 npc捏脸数据库 编辑:程序博客网 时间:2024/06/08 05:38

                                              java 线程池ThreadPoolExecutor

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

二、线程池ThreadPoolExecutor

   1.接口说明

[java] view plain copy
  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.代码

   

[java] view plain copy
  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

原创粉丝点击