线程池的基础知识
如果不了解线程池,可以先看一下基础知识。
详情见: https://www.cnblogs.com/expiator/p/9053754.html
核心线程数设置
IO密集型/CPU密集型的
CPU密集型:核心线程数 = CPU核数 + 1
CPU密集的意思是任务需要大量的运算,而没有IO阻塞,CPU一直全速运行。线程数一般只需要设置为CPU核心数的线程个数就可以了。
例如:一些业务复杂的计算和逻辑处理过程。
IO密集型:核心线程数 = CPU核数 * 2
IO密集型,就是程序中存在大量的 I/O 操作占用时间,导致线程空余时间很多,所以通常就需要开CPU核心数两倍的线程。当线程进行 I/O 操作 CPU 空闲时,启用其他线程继续使用 CPU,以提高 CPU 的使用率。
例如:数据库交互,文件上传下载,网络传输等。
在平常开发中,大部分的业务都属于IO密集型。
这些只是理论,实践还是得逐步优化。
做好压测,逐步调优,选择最合适的线程数。
核心线程数太小会怎样?
核心线程数太小,当核心线程数用完后,剩下的任务会进入阻塞队列,会有越来越多的任务处于阻塞状态。
在使用线程池异步获取返回值时,一般都会设置超时时间,如果阻塞的任务越来越多,那么任务就可能会频繁超时,可以尝试将核心线程数调大。
核心线程数太大会怎样?
当我们的线程数量配置的过大,我们的线程与线程之间有会争取 CPU 资源,这就会导致上下文切换。
上下文切换过多,必然增加线程的执行时间,影响了整体执行效率。
谨慎使用 newCachedThreadPool
由于newCachedThreadPool最大线程数设置为最大的Integer.MAX_VALUE,如果最大线程数maximumPoolSize达到最大,那么会导致OOM异常。
谨慎使用 newFixedThreadPool
newFixedThreadPool,使用的LinkedBlockingQueue()是一个无界队列,队列长度可达到Integer.MAX_VALUE,如果瞬间请求非常大,会有OOM的风险
要不要使用公共线程池?
- 普通的业务,可以使用公共线程池。避免系统使用的线程过多。
- 核心的业务,最好使用独立线程池,不要用公共线程池。避免受到其他业务的影响。
使用线程池要注意
- 参数最好写成配置,不要写死。线上发生问题时,能快速修复。
- 线程池获取返回值,必须设置超时时间。一般设置为2s,具体看业务。
- 线程池超时,最好能发送告警。及时发现异常。
- 做好压测,逐步调优,选择最合适的线程数。
其他资料:
https://www.cnblogs.com/expiator/p/9053754.html
https://www.cnblogs.com/expiator/p/10193315.html
https://www.zhihu.com/question/382614051/answer/1133960919
https://mp.weixin.qq.com/s?__biz=MzkwNjMwMTgzMQ==&mid=2247499989&idx=1&sn=b9de5a981d4103efbb1b34fa7fe7affb&chksm=c0e8183df79f912b27d275b2ea37a6b4d686dbff0307d1d9f224a0308e102245db56ccd08593&scene=178&cur_album_id=2749033117763747845#rd