线程池的七个参数(加上四种常见的工作队列和拒绝策略)

哎哟,说起线程池的参数,这可是一门大学问啊。
来来来,我给你细说细说。

首先得说核心线程数,这叫corePoolSize,这就像是你公司里的正式员工,不管闲不闲着,你得养着他们。
我记得当年我在2 01 5 年做项目的时候,这个核心线程数一般是按照CPU核心数来定的,比如说4 核CPU,那我就设置成4
然后是最大线程数,maxPoolSize,这就像是你公司里可以雇佣的临时工数量。
当任务多到工作队列都满了,这个数字就决定了你能雇佣多少临时工。
我之前做的一个项目,这个数字是设置成了2 0。

再来说空闲线程存活时间,keepAliveTime,这就像是你公司里的临时工,如果闲得蛋疼,你可以让他们休息一段时间再走。
我那时候是设置成6 0秒,单位是秒。

unit,这单位啊,就像是你问人家多高,回答是1 米8 还是1 8 0厘米,这取决于你问问题的方式。
我那时候是用的TimeUnit.SECONDS。

工作队列,workQueue,这就像是你公司里的仓库,任务都先放在这里等着。
我之前用的ArrayBlockingQueue,这玩意儿是有界的,就像仓库有最大容量一样。

threadFactory,这就像是你公司里给员工定名字,或者决定他们是正式工还是临时工。
我那时候是自定义了一个线程工厂,把线程名字改成了“Worker”。

handler,这就像是你公司里对待那些没活干的临时工的策略。
我那时候用的是CallerRunsPolicy,就是让提交任务的线程自己处理。

说到工作队列,我得说说常见的几种:
ArrayBlockingQueue,这就像是有边界的仓库,先进先出,队列满了就创建新线程,直到达到最大线程数。

LinkedBlockingQueue,这就像是无边界的仓库,只要空间足够,可以一直存,满了就等着,直到有空间。

SynchronousQueue,这就像是个临时停车场,没有车位就等着,直到有车离开。

PriorityBlockingQueue,这就像是个有优先级的停车场,车按优先级停,先到先得。

拒绝策略嘛,常见的有:
CallerRunsPolicy,就是让提交任务的线程自己处理。

AbortPolicy,默认的,直接丢弃任务,还给你抛个异常。

DiscardPolicy,直接丢弃任务,不给你抛异常。

DiscardOldestPolicy,丢弃最早的任务,然后尝试把新任务放进去。

这些参数和策略,就像是调酒师手中的各种酒,可以根据你的需求来搭配。
记得,要根据实际应用场景来配置,别瞎搞。

线程池的四种创建方式及区别

上周,我遇到个问题,线程池的线程数量有点诡异。
核心线程数是0,非核心线程数是MAX_VALUE,看起来队列是空的,但实际上总感觉是满的。
所以,每次有任务来,都会创建新的非核心线程。
这些非核心线程如果闲了超过6 0秒,就会自动消失。

2 02 3 年,我试了newFixedThreadPool,这玩意儿就像个定长的队伍。
还没到人数上限,每个任务一来就开个新线程。
但要是超了,任务就排进队列里。
这队列是无界的,所以在资源紧张的时候,很容易出现内存溢出(OOM)。

我那个朋友提到,和newSingleThreadPool比起来,这个线程池的核心线程数不是1 ,而是参数里传的那个数。
而且,它和newSingleThreadPool一样,队列也是无界的。

我另一个朋友说,newSingleThreadPool只创建一个线程,按顺序执行任务。
如果这个线程出毛病了,另一个线程会顶上继续执行。
核心线程数和非核心线程数都是1 ,队列也是无界的。
这个线程池的最大特点就是能保证任务的执行顺序,而且同一时间只有一个线程在干活。

2 02 3 年,我还试了newScheduedThreadPool,这个线程池不仅定长,还支持定时和周期性的任务执行。
核心线程数可以自己设置,非核心线程数是MAX_VALUE。
它有个叫DelayedWorkQueue的有序队列,会根据任务下次执行的时间来排序。

线程池的工作逻辑是这样的:先看核心线程数是否已满,不满就开个新线程;满了,再看队列是否满,不满就加入队列;队列也满了,再看线程池是否满,不满就再开个新线程;如果线程池也满了,就只能用拒绝策略了。

默认的拒绝策略是AbortPolicy,直接抛出异常。
但这样处理不太优雅。
可以自己实现拒绝策略,比如CallerRunsPolicy或者自定义一个。

我有个想法,如果想处理不重要的任务,用DiscardPolicy或者DiscardOldestPolicy丢弃任务也是可以的。
不过,这些策略都有各自的适用场景。

算了,说这么多,你看着办吧。

javanewcachedthreadpool线程池使用在什么情况下?

上个礼拜写代码,突然收到一个用户反馈,说系统卡得不行。
我一看,嚯,后台任务跑太多了。
之前没注意,直接用newCachedThreadPool,结果任务一多,线程也跟着疯狂创建,内存直接飙升到百分之九十多。
那会儿是周三下午,三点钟左右,办公室里空调嗡嗡响,我赶紧改成FixedThreadPool,线程数设成十个,任务慢慢排队处理,系统立马就稳了。
想想看,这newCachedThreadPool确实牛,能根据忙闲自动伸缩,但要是任务一直没完没了,那内存真得遭不住。
等等,还有个事,我后来又琢磨过,要是任务特别重,比如秒杀活动那种,用FixedThreadPool会不会有点浪费?毕竟闲着也是闲着,还得花钱租服务器。
可要是用newCachedThreadPool,万一瞬间涌入几万请求呢?这线程池直接给你整出几百上千个,服务器不直接炸了?这事儿真挺纠结的。