线程池的线程数设置

线程池的基础知识

如果不了解线程池,可以先看一下基础知识。
详情见: 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 资源,这就会导致上下文切换。
上下文切换过多,必然增加线程的执行时间,影响了整体执行效率。

最大线程数太小会怎样?

当核心线程数用完,阻塞队列放满后,线程池中的线程超过最大线程数就会触发拒绝策略。
如果最大线程数太小,那么可能会频繁触发拒绝策略。

最大线程数太大会怎样?

最大线程数太大,线程池中的线程数量会越来越多,JVM内存无法存放如此多的对象,那么可能会导致OOM异常。

谨慎使用 newCachedThreadPool

由于newCachedThreadPool最大线程数设置为最大的Integer.MAX_VALUE,如果最大线程数maximumPoolSize达到最大,那么会导致OOM异常。

谨慎使用 newFixedThreadPool

newFixedThreadPool,使用的LinkedBlockingQueue()是一个无界队列,队列长度可达到Integer.MAX_VALUE,如果瞬间请求非常大,会有OOM的风险

最好自定义线程池ThreadPoolExecutor

最好使用自定义线程池ThreadPoolExecutor,控制好最大线程数、阻塞队列长度,避免OOM。

减少接口耗时,胜于盲目调大线程数

优化接口性能,减少接口耗时,比盲目调大线程数更有用。
接口耗时越少,线程处理得越快,那么线程池中的线程就能持续复用,不会继续增加线程数,也不容易触发拒绝策略。
接口的性能优化,详情见:https://www.cnblogs.com/expiator/p/17094135.html

要不要使用公共线程池?

  • 普通的业务,可以使用公共线程池。避免系统使用的线程过多。
  • 核心的业务,最好使用独立线程池,不要用公共线程池。避免受到其他业务的影响。

线程池任务获取返回值,必须设置超时时间。

线程池获取返回值,必须设置超时时间,否则线程有可能一直阻塞。
超时的任务,必须打印错误日志。如果能发送告警更好。
超时时间,一般设置为2s,具体看业务。

线程池参数,动态配置

  • 参数最好写成配置,不要写死。线上发生问题时,能快速修复。
  • 做好压测,逐步调优,选择最合适的线程数。

自定义线程池

详情见: https://www.cnblogs.com/expiator/p/17140760.html

其他资料:

https://www.cnblogs.com/expiator/p/9053754.htmlhttps://www.cnblogs.com/expiator/p/10193315.htmlJava项目中,线程池中线程数量太大会有什么影响? - 知乎接口突然超时10宗罪。。。

你可能感兴趣的:(java)