Toc
  1. 重要属性
  2. 线程数计算方法
  3. 动态化线程池
Toc
0 results found
BOBO
Java线程池
2020/08/20 Java基础

重要属性

corePoolSize 核心线程数
maxmumPoolSize
keepLiveTime
Queue
image.png

线程数计算方法

方案 问题
Ncpu=number of CPUsUcpu=target CPU utilization,0≤Ucpu≤1CW=ratio of wait time to compute timeThe optimal pool size for keeping the processors at the desired utilization isNthreads=NcpuUcpu∗(1+CW) 出自《Java 并发编程实践》
该方案偏理论化。首先,线程计算的时间和等待的时间要如何确定呢?这个在实际开发中很难得到确切的值。另外计算出来的线程个数逼近线程实体的个数,Java 线程池可以利用线程切换的方式最大程度利用 CPU 核数,这样计算出来的结果是非常偏离业务场景的
coreSize=2∗NcpumaxSize=25∗Ncpu 没有考虑应用中往往使用多个线程池的情况,统一的配置明显不符合多样的业务场景。
coreSize=tpstimemaxSize=tpstime∗(1.7∼2) 这种计算方式,考虑到了业务场景,但是该模型是在假定流量平均分布得出的。业务场景的流量往往是随机的,这样不符合真实情况。

tomcat 是请求连接数默认 200,如果是 IO 密集型,那么在 CPU 调度其他线程时,IO 任务还可以处理,这样更多线程数能同时处理更多 IO 任务,CPU 密集型就没办法了,所以线程都要争夺 CPU 资源,一般设置 CPU 核心数+1 就行了。

一个 CPU 核都想跑满 100%,理论 线程数= (IO 时间+ CPU 计算时间)/ CPU 计算时间;如果 CPU 密集型 的 IO 时间 ≈0,此时为 CPU 核数;网上流传的 IO 密集型认为 IO 时间 ≈CPU 时间,此时为 CPU 核数*2;常规的 Web 服务下 IO 时间远大于 CPU 时间,所以 dubbo 设置为 200,这个我猜主要是参考了业界老油条 Tomcat 的默认配置,不同场景下可能有不小的优化空间。

动态化线程池

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

支付宝
微信
IOC
Simple is Awesome