java的线程池有几种 java线程的创建方式( 八 )



图16 动态修改线程池参数新旧流程对比
基于以上三个方向对比 , 我们可以看出参数动态化方向简单有效 。
3.3 动态化线程池
3.3.1 整体设计
动态化线程池的核心设计包括以下三个方面:

  1. 简化线程池配置:线程池构造参数有8个 , 但是最核心的是3个:corePoolSize、maximumPoolSize , workQueue , 它们最大程度地决定了线程池的任务分配和线程分配策略 。考虑到在实际应用中我们获取并发性的场景主要是两种:(1)并行执行子任务 , 提高响应速度 。这种情况下 , 应该使用同步队列 , 没有什么任务应该被缓存下来 , 而是应该立即执行 。(2)并行执行大批次任务 , 提升吞吐量 。这种情况下 , 应该使用有界队列 , 使用队列去缓冲大批量的任务 , 队列容量必须声明 , 防止任务无限制堆积 。所以线程池只需要提供这三个关键参数的配置 , 并且提供两种队列的选择 , 就可以满足绝大多数的业务需求 , Less is More 。
  2. 参数可动态修改:为了解决参数不好配 , 修改参数成本高等问题 。在Java线程池留有高扩展性的基础上 , 封装线程池 , 允许线程池监听同步外部的消息 , 根据消息进行修改配置 。将线程池的配置放置在平台侧 , 允许开发同学简单的查看、修改线程池配置 。
  3. 增加线程池监控:对某事物缺乏状态的观测 , 就对其改进无从下手 。在线程池执行任务的生命周期添加监控能力 , 帮助开发同学了解线程池状态 。

java的线程池有几种 java线程的创建方式


图17 动态化线程池整体设计
3.3.2 功能架构
动态化线程池提供如下功能:
  • 动态调参:支持线程池参数动态调整、界面化操作;包括修改线程池核心大小、最大核心大小、队列长度等;参数修改后及时生效 。
  • 任务监控:支持应用粒度、线程池粒度、任务粒度的Transaction监控;可以看到线程池的任务执行情况、最大任务执行时间、平均任务执行时间、95/99线等 。
  • 负载告警:线程池队列任务积压到一定值的时候会通过大象(美团内部通讯工具)告知应用开发负责人;当线程池负载数达到一定阈值的时候会通过大象告知应用开发负责人 。
  • 操作监控:创建/修改和删除线程池都会通知到应用的开发负责人 。
  • 操作日志:可以查看线程池参数的修改记录 , 谁在什么时候修改了线程池参数、修改前的参数值是什么 。
  • 权限校验:只有应用开发负责人才能够修改应用的线程池参数 。

java的线程池有几种 java线程的创建方式


图18 动态化线程池功能架构
参数动态化
JDK原生线程池ThreadPoolExecutor提供了如下几个public的setter方法 , 如下图所示:
java的线程池有几种 java线程的创建方式


图19 JDK 线程池参数设置接口
JDK允许线程池使用方通过ThreadPoolExecutor的实例来动态设置线程池的核心策略 , 以setCorePoolSize为方法例 , 在运行期线程池使用方调用此方法设置corePoolSize之后 , 线程池会直接覆盖原来的corePoolSize值 , 并且基于当前值和原始值的比较结果采取不同的处理策略 。对于当前值小于当前工作线程数的情况 , 说明有多余的worker线程 , 此时会向当前idle的worker线程发起中断请求以实现回收 , 多余的worker在下次idle的时候也会被回收;对于当前值大于原始值且当前队列中有待执行任务 , 则线程池会创建新的worker线程来执行队列任务 , setCorePoolSize具体流程如下:

推荐阅读