线程池构造详解

Java中的Class ThreadPoolExecutor

public class ThreadPoolExecutor extends AbstractExecutorService

该类是线程池的核心类,使用线程池时就是实例化该类的过程,这个类提供了4个构造方法:

//创建一个新的 ThreadPoolExecutor与给定的初始参数和默认线程工厂和拒绝执行处理程序。 
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue);
 
//创建一个新的 ThreadPoolExecutor与给定的初始参数和默认线程工厂。 
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler); 
 
//创建一个新的 ThreadPoolExecutor与给定的初始参数和默认拒绝执行处理程序。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory); 
  
//创建一个新 ThreadPoolExecutor给定的初始参数。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);  

参数详解

构造方法中一共使用到了七个参数,含义分别为:

  • corePoolSize - 即使空闲时仍保留在池中的线程数,除非设置 allowCoreThreadTimeOut
  • maximumPoolSize - 池中允许的最大线程数
  • keepAliveTime - 当线程数大于核心线程数时,这是多余的空闲线程在终止前等待新任务的最大时间。
  • unit - keepAliveTime参数的时间单位
  • workQueue - 用于在执行任务之前使用的队列。 这个队列将仅保存execute方法提交的Runnable任务。
  • threadFactory - 执行程序创建新线程时使用的工厂
  • handler - 执行被阻止时使用的处理程序,因为达到线程限制和队列容量

线程池工作顺序

线程池的工作顺序为:

  1. 线程池创建,准备好corePoolSize数量的核心线程,准备接收任务
  2. 当core满了时,就将再进来的任务放入到阻塞队列中,空闲的core线程就去自动去阻塞队列获取任务执行
  3. 当阻塞队列满了时,就去直接开新进程执行,最大只能开到maximumPoolSize数量的线程
  4. 当开到最大线程数依然满足不了任务数时,就会调用RejectedExecutionHandler拒绝任务
  5. 如果当前线程池具有多于corePoolSize线程,则如果空闲超过keepAliveTime,则多余的线程将被终止max线程都执行完成

拒绝策略

当执行程序对最大线程和工作队列容量使用有限边界并且饱和时,会触发拒绝策略,RejectedExecutionHandler提供了四个预定义的处理程序策略:

  • 默认ThreadPoolExecutor.AbortPolicy ,丢弃任务并抛出异常。

  • 在ThreadPoolExecutor.CallerRunsPolicy中,由调用execute本身的线程运行任务, 这提供了一个简单的反馈控制机制,将降低新任务提交的速度。

  • 在ThreadPoolExecutor.DiscardPolicy中 ,简单地删除无法执行的任务,但不抛出异常。

  • 在ThreadPoolExecutor.DiscardOldestPolicy中 ,如果执行程序没有关闭,则工作队列头部的任务被删除,然后重试执行(可能会再次失败,导致重复)。

为什么要使用线程池

减低资源消耗

通过重复利用已经创建好的线程降低线程创建和销毁带来的损耗

提高相应速度

当线程池中有等待分配任务的线程时,新任务来临时无需创建新线程即可执行

提高线程的可管理性

线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来的系统开销。无限的创建和销毁线程不仅消耗系统资源,还减低系统的稳定性,使用线程池可进行统一分配。

posted @ 2021-06-20 18:33  bGpi  阅读(205)  评论(0编辑  收藏  举报