java线程池 如何构建一个线程立即到拉到MAX数量跑业务,线程到MAX了,额外的队列可以存储任务的线程池...

背景:JDK的线程池的运作原理 :

JDK的线程池的构造函数有7个参数,分别是corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。先复习一下 https://blog.csdn.net/ye17186/article/details/89467919


上述内容是网上对于线程池的参数的描述,需要关注的一个点:

1)任务进入线程池队列,先启动WORKER线程到 CORE的数量,然后再填写线程池的缓冲队列,队列满了以后(如果可以满),再增加WORKER线程到MAX配置数量。

下面是源码:(源码就是这样,也验证过,是这个逻辑,简单说,先CORE 再队列,队列满了以后再拉线程到MAX数量)

2)这样会有缺陷,为什么一定要 满足 队列满了,再拉线程,我想优先拉线程怎么办 ? 不好意思,JDK只有一个办法:设置队列大小为1,那么就基本上马上就会拉新线程了(但是作为数据缓冲区的队列,削峰填谷的优势就无法使用了)

那么如果期望 优先 先拉线程数量到MAX,再把任务放到队列缓存区怎么办 ?

业务场景需要满足: 1)任务量大了,线程立即到拉到MAX 数量跑业务。 2)线程到MAX了,额外的队列可以存储任务,做削峰填谷使用。

(core size是闲时最低线程数量,如果线程数量太多,会导致线程内存开销以及 太多线程无效轮询消耗)

方案一: 看到源码,自己去实现一个线程池的实现,重写EXECUTE方法,调整逻辑,先拉WORKER到MAX然后放入队列可以达成

项目中,准备上方案一的时候,发现代码量不小,这个问题应该很多人都遇到了,有没有现成的可以使用?

重写JDK源码会带来工作量,维护,以及升级JDK的风险,明显是一种不好的办法。

方案二:再找就发现了这样一篇文档:

https://blog.csdn.net/qq271859852/article/details/104860255/

果然,遇到这个问题的不止一个, 事实上 tomcat 和dubbo 都这样干了!

非常有意思的是,是在队列的OFFER函数中做文章(有点欺骗JDK的线程池 EXECUTE的意思)很难想到这种方案。

我们要使用:两行代码就满足了我们的诉求:

引用对象:当然是用DUBBO也是一样,已验证、有效。

PS: 额外的思考:

1)为什么?JDK默认要使用先队列再拉MAX WORKER的方式? 可能是JDK认为线程池任务大多数都是 CPU密集型的任务,那么启动太多的CPU带来的价值不大、或者拉线程的有成本,队列满了再拉。

2)怎么选?如果任务是CPU密集使用JDK自带的线程池策略就够了,如果是IO型任务,有较多阻塞场景(这就是为什么TOMCAT 和RPC的DUBBO需要的原因)就需要使用线程数优先,再进入队列的模式(IO密集型任务,有IO阻塞,JDK自带线程池的策略难以满足要求)。

3)客观的说,JDK应该把这个配置 做成配置项(到底是先进入队列,再拉线程到MAX,还是先拉线程到MAX再进入队列)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值