Java并发工具ThreadPoolExecutor线程池使用讲解2

87 篇文章 1 订阅
86 篇文章 2 订阅

本文接着前面那篇文章继续介绍Java并发工具ThreadPoolExecutor(线程池)。首先回顾一下,线程池主要是用于充分挖掘多核CPU的运算能力、加快任务处理速度,减少线程上下文切换。线程池依赖5个配置参数,即corePoolSize、maximumPoolSize、阻塞队列、饱和策略及线程工厂。

前面已介绍corePoolSize、maximumPoolSize和阻塞队列以及他们之间的变化关系。阻塞队列是否被放满将影响线程池中worker线程的创建。关于阻塞队列,如果我们传入不同类型的阻塞队列(实现类),也导致线程池使用不同的排队策略。注意,后文简称阻塞队列为队列

1. 线程池的排队策略

A. 直接移交:队列的存储空间为0,例如SynchronousQueue。当把这种队列传给线程池之后,任务只能交给线程执行,不能存储在队列中。可以认为SynchronousQueue是一个刚创建出来就是满的阻塞队列并且永远都是满的。假如线程池中的线程个数未达到最大值,则每次往线程池提交任务,则它要么被空闲worker线程取出执行,要么被新创建的worker线程取出来执行。

Java并发工具ThreadPoolExecutor线程池使用讲解2

B. 无界队列:队列的存储空间无限(不考虑内存空间),例如LinkedBlockingQueue。使用这种队列的线程池,worker线程的个数达到corePoolSize之后不再增加,新的任务全部都存入队列,所以maximumPoolSize参数不会产生实质性的作用。这种队列适合任务之间无依赖关系的场景,也可以用于对突然增长的高并发请求进行平滑处理或削峰

Java并发工具ThreadPoolExecutor线程池使用讲解2

C. 有界队列:有空间大小限制的阻塞队列,例如ArrayBlockingQueue。使用这种队列的时候,队列大小及maximumPoolSize这两个参数是比较难调整的。你可以多观察CPU利用率、线程上下文切换消耗、吞吐量等指标,结合任务类型(是否容易阻塞)等来调整这两个参数。假如任务的IO操作较多,那么系统就有较多空余时间执行上下文切换,此时可以适当增加maximumPoolSize让线程多一些;如果任务计算量较多,则可以适当增大队列、减少线程数,腾出上下文切换时间给任务。一般而言,调小队列大小之后就应该调大一些maximumPoolSize,反之亦然。

2. 线程池的饱和处理策略

当线程池已关闭或者达到饱和状态(队列和线程数均达到上限)时,再有线程提交任务,就会触发饱和处理策略。有4种策略:

  1. ThreadPoolExecutor.AbortPolicy(放弃执行,提交的线程一调用submit()就会接收到RejectedExecutionException异常);
  2. ThreadPoolExecutor.CallerRunsPolicy(在提交的线程中执行,提交的线程自己来运行这个任务,此时异步操作降级成同步操作);
  3. ThreadPoolExecutor.DiscardPolicy(丢弃,这个任务被静静的扔掉,没有反馈);
  4. ThreadPoolExecutor.DiscardOldestPolicy(丢弃最老的任务,把队列头部的那个任务丢掉,然后再次尝试提交)。

注意:JDK给线程池提供的饱和策略是可以扩展的,一般以上4种策略够用了。

3. 线程池如何关闭

当线程池不再被变量引用且线程池中线程数等于0时,线程池将自动关闭(利用Object.finalize实现)。但是又因为默认情况下,线程池中对应corePoolSize的线程不会终止,所以线程池依然不能自动终止。可借助allowCoreThreadTimeOut(boolean)让核心worker线程空闲一段时间之后自动终止,这样线程池就可以自动关闭了。另外,也可以手动调用shutdown()来显式关闭线程池。还有一种比较暴力的关闭方式shutdownNow(),它除了不允许新任务再提交,还会中断正在执行任务的worker线程,让线程池立即关闭,所以可能导致数据丢失。shutdown()与shutdownNow()的区别与联系如下图所示,请耐心分析,应该好懂的(包括设置线程池关闭状态以禁止新任务提交、给worker发中断、丢弃任务队列等)。

Java并发工具ThreadPoolExecutor线程池使用讲解2

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值