多个场景共用一个大的线程池还是每个任务单独使用线程池

1.首先,项目中如果有多个场景需要使用线程池,那么最好的方式是:每一个业务场景使用独立的线程池。不要让所有的场景共用一个线程池。

分析:

1)独立的线城池之间互相不影响彼此的任务作业,更有利于保证本任务的独立性和完整性,更符合低耦合的设计思想

2)如果所有的场景共用一个线程池,可能会出现如下问题,举例:

比如有任务A、任务B、任务C   这三个任务场景共用一个线程池,配置如下

threadPool:
  corePoolSize: 20
  maximumPoolSize : 2000
  workQueue : 1000
  keepAliveSeconds: 300
  • 第1个参数 :corePoolSize 表示常驻核心线程数。如果等于0,则任务执行完成后,没有任何请求进入时销毁线程池的线程;如果大于0,即使本地任务执行完毕,核心线程也不会被销毁。这个值的设置非常关键,设置过大会浪费资源,设置的过小会导致线程频繁地创建或销毁。
  • 第2个参数:maximumPoolSize 表示线程池能够容纳同时执行的最大线程数。从上方的示例代码中第一处来看,必须大于或等于1。如果待执行的线程数大于此值,需要借助第5个参数的帮助。缓存在队列中。如果maximumPoolSize 与corePoolSize 相等,即是固定大小线程池。
  • 第3个参数: workQueue 表示缓存队列。如果线程池里的线程数大于corePoolSize ,就会放到缓存队列,缓存队列满了会创建新线程到maximumPoolsize;直到当请求的线程数大于maximumPoolSize时,会执行设定的策略,默认是拒绝创建策略。(注意:当线程池里的线程数大于corePoolSize且小于maximumPoolSize时,这时候再有请求的线程就会放到缓存队列,注意只是放到缓存队列但是不创建新的线程,直到请求的线程存满缓存队列时,才会开始创建新的线程,直到maxmunPoolSize就会拒绝创建或者执行提前设定的策略。
  • 第4个参数:  keepAliveSeconds
    表示线程池中的线程空闲时间,当空闲时间达到keepAliveSeconds值时,线程被销毁,直到剩下corePoolSize 个线程为止,避免浪费内存和句柄资源。在默认情况下,当线程池的线程大于corePoolSize 时,keepAliveSeconds才会起作用。但是ThreadPoolExecutor的allowCoreThreadTimeOut 变量设置为ture时,核心线程超时后也会被回收。

 当任务A请求量剧烈增加的时候就会导致任务B和任务C,没有可用的线程  可能出现迟迟获取不到资源的情况。比如任务A同时有3000个线程请求,此时就可能会导致  任务B和任务C分配不到资源或者分配到很少的线程资源。

所以为了避免这种情况的产生,最好的方式是建立独立的线程池。

这样不管任务A的线程是堵塞还是其他原因,都不会影响任务B和任务C,同理任务B、任务C也一样不会影响其他场景任务的执行。

2.注:

1.JDK自带的类使用了很多的线程池.
2.很多开源框架使用了大量的线程池.
3.自己的应用也会创建多个线程池.
4.不要在意什么CPU密集还是IO密集(这是一种人云亦云的说法,至少java语言来说不要考虑什么IO还是CPU).
5.多少个线程池,每个线程池提供多少线程,必须经过详细的测试,不能人云亦云,不能参考别人.
不同的业务,不同的场景,线程池的个数,线程的数量都是不一样的.

一台服务器硬件资源是固定的,比如20核心40线程的CPU,能部署一个应用,就尽量部署一个,不要什么都部署.

经过测试你会发现:

有时候线程创建多了会消耗大量的内存,关键是无法提升性能.
当你创建1个线程,5线程,10线程时,处理数据的性能差不多,那就不应该创建多个.
所以,线程池相关的问题,需要经过长时间的测试,不断的测试最终提供一套符合目前需求的参数.
posted @ 2022-01-04 17:48  初仰  阅读(3373)  评论(2编辑  收藏  举报