怎么根据业务场景确定线程池的参数corePoolSize和maximumPoolSize?
1 个回答
明知不可为而为之就是我最大的诚意夜太### 方法一 计算密集型任务 因为是计算密集型任务,可以理解为每个任务在执行期间基本没有IO操作,全部都在CPU时间片中执行。所以可以理解为CPU就是满载的,CPU利用率就是100%,其实线程数等于CPU数就可以的,但是由于需要考虑到计算密集型的线程恰好在某时因为发生一个页错误或者因其他原因而暂停,此时应该需要有一个“额外”的空闲线程来获得时间片,然后执行,可以确保在这种情况下CPU周期不会中断工作,充分利用CPU。 ```java 最佳线程数=CPU的数量+1 ``` ### 方法二 IO密集型任务 这种任务在执行时,需要进行一些IO操作,所以为了充分利用CPU,应该在线程进行IO操作时,就让出时间片,CPU进行上下文切换,执行其他线程的任务,保证CPU利用率尽可能达到100%。 如果任务有50%的时间需要CPU执行状态,其他时间进行IO操作,则程序所需线程数为CPU数量的1除以0.5,也就是2倍。如果任务有20%的时时间需要CPU执行,其他时间需要进行IO操作,最佳线程数也就是1除以0.2,也就是CPU数的5倍。 所以公式为 ```java 最佳线程数 = CPU数量/(每个任务中需要CPU执行的时间的比例) = CPU数量/(CPU运行时间/任务执行总时间)=CPU数量/(CPU运行时间/(CPU运行时间+IO操作时间)) 所以最终公式为 最佳线程数/CPU数量 = CPU运行时间/(CPU运行时间+IO操作时间) ``` **不足** 但是在实际线上运行的环境中,每个任务执行的时间是各不相同的,而且我们其实是不太方便去监测每个任务执行时需要的CPU执行时间,IO操作时间的,所以这种方法只是一种理论。 ### 方法三 动态化线程池 这种其实是美团他们做的一个线程池监测平台,主要把任务分成两种, **追求响应时间的任务** 一种是追求响应时间的任务,例如使用线程池对发起多个网络请求,然后对结果进行计算。 这种任务的最大线程数需要设置大一点,然后队列使用同步队列,队列中不缓存任务,任务来了就会被执行。判断线程池资源不够用时,一般是发现活跃线程数/最大线程数>阀值(默认是0.8)时,或者是线程池抛出的RejectedExecut异常次数达到阀值,就会进行告警。然后程序员收到告警后,动态发送修改核心线程数,最大线程数,队列相关的指令,服务器进行动态修改。 **追求高吞吐量的任务** 假设说需要定期自动化生成一些报表,不需要考虑响应时间,只是希望如何使用有限的资源,尽可能在单位时间内处理更多的任务,也就是吞吐量优先的问题。 这种就是使用有界队列,对任务进行缓存,然后线程进行并发执行。判断线程池资源不够用时,一般是发现等待队列中的任务数量/等待队列的长度>阀值(默认是0.8)时,或者是线程池抛出的RejectedExecut异常次数达到阀值,就会进行告警。然后程序员收到告警后,动态发送修改核心线程数,最大线程数,队列相关的指令,服务器进行动态修改。 ThreadPoolExecutor提供了如下几个public的setter方法  调用corePoolSize方法之后,线程池会直接覆盖原来的corePoolSize值,并且基于当前值和原始值的比较结果采取不同的处理策略。(总得来说就是,多退少补的策略) 对于新corePoolSize<当前工作线程数的情况: 说明有多余的worker线程,此时会向当前idle状态的worker线程发起中断请求以实现回收,多余的worker在下次idel的时候也会被回收。 对于新corePoolSize>当前工作线程数且队列中有任务的情况: 如果当前队列中有待执行任务,则线程池会创建新的worker线程来执行队列任务。 setCorePoolSize的方法的执行流程入下图所示:  扩展资料:[Java并发(八)计算线程池最佳线程数](https://www.cnblogs.com/jpfss/p/11016169.html)发布于 2022-02-07 17:32 •IP属地 西藏举报评论收藏
公众号进入网站体验更佳

