线程池ThreadPoolExecutor

线程池.png

ThreadPoolExecutor的构造方法:

public ThreadPoolExecutor(int corePoolSize,  
                          int maximumPoolSize,  
                          long keepAliveTime,  
                          TimeUnit unit,  
                          BlockingQueue<Runnable> workQueue,  
                          ThreadFactory threadFactory,  
                          RejectedExecutionHandler handler)  

说明

  • corePoolSize: 线程池维护线程的最少数量
  • maximumPoolSize:线程池维护线程的最大数量
  • keepAliveTime: 线程池维护线程所允许的空闲时间
  • unit: 线程池维护线程所允许的空闲时间的单位
  • workQueue: 线程池所使用的缓冲队列
  • handler: 线程池对拒绝任务的处理策略

逻辑

  1. 当池子线程数量小于corePoolSize就新建线程,并处理请求

  2. 当池子大小等于corePoolSize,就会将请求放入workQueue中,等池子里的线程空闲了,就去从workQueue中取任务并处理

  3. 当workQueue放不下新入的任务时,新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize就用RejectedExecutionHandler来做拒绝处理

  4. 另外,当池子的线程数大于corePoolSize的时候,多余的线程会等待keepAliveTime长的时间,如果无请求可处理就自行销毁

理解

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

参数

unit 可选的参数为java.util.concurrent.TimeUnit中的几个静态属性:

  • NANOSECONDS
  • MICROSECONDS
  • MILLISECONDS 毫秒
  • SECONDS 秒

workQueue 常用的是:java.util.concurrent.ArrayBlockingQueue

  • SynchronousQueue 直接提交,它将任务直接提交给线程而不保持它们。
  • LinkedBlockingQueue 无界队列,将导致在所有 corePoolSize 线程都忙的情况下将新任务加入队列。
  • ArrayBlockingQueue 有界队列,有助于防止资源耗尽,但是可能较难调整和控制。
    ...

handler 有四个选择:

  • ThreadPoolExecutor.AbortPolicy()
    抛出java.util.concurrent.RejectedExecutionException异常

  • ThreadPoolExecutor.CallerRunsPolicy()
    当抛出RejectedExecutionException异常时,会调用rejectedExecution方法
    (如果主线程没有关闭,则主线程调用run方法,源码如下

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {            
         if (!e.isShutdown()) {                
                 r.run();            
         }
        }
)
  • ThreadPoolExecutor.DiscardOldestPolicy()
    抛弃旧的任务

  • ThreadPoolExecutor.DiscardPolicy()
    抛弃当前的任务

推荐阅读更多精彩内容