线程池类——ThreadPoolExecutor

线程池深入

线程池的架构

线程池的顶层接口Executor接口只定定义了一个方法
execute(Runnable task);
即提交异步任务的方法,它的子接口ExecutorService接口在它的基础上定义了
能够获得异步返回结果的提交方法
Future submit(Callable task);
我们经常使用的线程池快捷创建工厂Executors,标准线程池创建类DefaultThreadPoolExecutor都是实现了该接口,DefaultThreadPoolExecutor定义了ExecrtorService接口的默认实现,接下来重点介绍的ThreadPoolExecutor标准线程池类就是该类的子类。

标准线程池类ThreadPoolExecutor

一般的开发中建议使用标准线程池类ThreadPoolExecutor类去创建线程池,它可以根据场景的变化灵活的设置线程池的参数,从而避免快捷线程池工厂Executor可能带来的问题。构造线程池的构造方法如下:
public ThreadPoolExecutor(
int corePoolSize , //核心线程数
int maxPoolSize, //最大线程数
int keepAliveTime, //非核心线程存活时间
TimeUnit unit , // 时间的单位
BlockingQueue queue, //任务阻塞队列
ThreadFactory factory , //线程工厂
RejectExecutonHanlder hanlder //线程池的拒绝策略
);
乍一看参数很多,其实很容易理解
1.corePoolSize 核心线程数
核心线程数,故名思意是线程池中最核心的线程的数量,当有任务提交时,如果线程池中的线程还没有达到核心线程数,那么无论线程池中有没有空闲线程,线程池都会优先创建一条核心线程来执行异步任务,且核心线程不会因空闲而被回收
2.maxPoolSize 最大线程数
即加上核心线程,该线程池中最大能创建几个线程,当核心线程都在忙碌,阻塞队列也已经满时,线程池就会创建非核心线程来执行队列中的任务,当这些非核心线程空闲且时间超过设定的阈值时,非核心线程会被线程池回收
3.blockingQueue 任务阻塞队列
阻塞队列是当线程池中的核心线程都在忙碌时,对于新提交的任务,线程池不会立即创建非核心线程执行任务,而是将任务放入阻塞队列,当核心线程繁忙且阻塞队列已满时,才会创建非核心线程执行队列中的任务,一般有五中常用的阻塞队列
(1)ArrayBlockingQueue
这是基于数组实现的阻塞队列,完全遵循先进先出FIFO的顺序,我们要在创建时为它设置容量。
(2)LinkedBlockingQueue
基于链表实现的阻塞队列,我们可以在创建时为其指定容量,如果不指定,该队列默认为无限容量,可以容纳无穷个任务直到系统资源耗尽,Executor的
newSingleExecutor()和newFixedThreadPool()就使用了这个阻塞队列
(3)PriorityBlockingQueue
这是一个拥有优先级的阻塞队列
(4)DelayQueue
基于ProirityBlockingQueue实现的,具有“延时执行”,“周期任务”等特性的阻塞队列,该队列有一个过期时间,即只有在队列中达到过期时间的任务才可以被出队,从而达到延时的效果
(5)SynchronousQueue
同步阻塞队列,该队列的特点是它不保存任何任务,即任务的入队和出队是同步的,当一个任务入队,必须有一个线程将其执行,否则入队操作会一直阻塞。

4.ThreadFactory 线程工厂
线程工厂接口只定义了一个方法就是用来创建一个线程,通过指定线程工厂,我们可以对线程池中线程的优先级,线程名,守护线程等属性进行设置,如果不给定线程工厂,那么默认使用defaultThreadFactory,默认线程工厂,该线程工厂线程都优先级都是相同的
5.rejectExecutionHanlder 线程池的拒绝策略
当线程被关闭,或线程达到最大线程数且无空闲线程,并且此时阻塞队列也不能容纳更多任务,当再有任务提交,线程池就会执行拒绝策略,我们可以通过实现RejectExecutionHanldere接口重写rejecctExecution方法自定义线程池的拒绝策略,jdk为我们提供了四种常用的拒绝策略
(1)AbortPolicy 拒绝并抛出异常
执行该策略,新提交的任务会被线程池拒绝并抛出RejectExecutionExecption异常,可以对该异常进行捕获。
(2)DiscardPolicy 拒绝并抛弃
执行该策略,新提交的任务会被线程池拒绝并丢弃,不会抛出任何异常
(3)DiscardOldestPolict 抛弃最老任务
执行该策略,会尝试从阻塞队列中抛弃最老的任务,也就是队头,再尝试将新任务添加到队尾
(4)CallerRunsPolicy 调用者执行策略
执行该策略,新提交的任务会被线程池拒绝并交给提交任务的线程自己执行。

总结:线程池的调度策略

1.线程池刚被创建时,内部并没有可使用的线程
2.当任务被提交时,线程池中的核心线程数并没有达到设定的值,此时无论线程池中有没有空闲的线程,线程池都会创建一个核心线程执行该任务。
3.当核心线程都处于工作状态,且不能再创建更多核心线程时,新任务会被加入阻塞队列,直到队列满。
4.当阻塞队列已满,又有新任务提交,线程池会创建非核心线程执行队列中的任务,但是线程总数不会超过设定最大值。
5.当线程池不能再创建线程,阻塞队列也已经满了,线程池对于提交的任务采取拒绝策略、
6.当非核心线程空闲时间超过设定的预期值,非核心线程会被回收。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值