线程池ThreadPoolExecutor通俗理解(无代码版)

目录

 

●目的

●说个故事

●正经解释

●继承关系


●目的

学习JAVA并发编程肯定是要用到线程池的知识,笔者也是花了一些时间,才算有点参悟。本文将通过例子和通俗的解释为各位读者讲解JAVA线程池的基本原理,不涉及源码和使用代码,让大家直观、大局的理解一下线程池。可以将本文作为JAVA线程池的启蒙科普文章查看,详细的使用和源码后续文章可能会发出。

本文写作过程中参考了《Java并发编程:线程池的使用》这篇文章,推荐给大家。

说个故事

通常大家介绍线程池都会以工厂作为例子,笔(chi)者(huo)将换个角度,给大家说个开炸串店的故事。

小朱自从上一家公司辞职后,就一直渴望创业开个炸串店。

第一天,小朱自己一个人支了个摊,在街边卖炸串,没想到刚开业生意就很红火,顾客络绎不绝。

几天后,小朱觉得这么做不行,顾客已经开始排起了长队,他想找点人来帮忙,于是,他贴了个招聘启事,寻找一个炸串师父帮忙烹饪,这样就可以两个人同时制作美味了。过了一段时间,炊具买好了,师父找到了,经培训上岗,开始了日常的经营。

转眼冬天到了,顾客越来越少,小朱觉得炸串师父已经用不到了,自己一个人就可以,还能省下一笔人工费。于是和炸串师父好生协商,补偿了人半个月的工资,把人辞退了,炊具也贱卖了

冬去春来,顾客居然成几何级增长,小朱一边高兴有钱赚,一边又愁没人手。保守估计,现在至少需要5个炸串师父才能忙的过来,咋办,贴招聘启事,一个一个招咯,而且还得再去买5套炊具。

某天,小朱遇到了一个古灵精怪的顾客小陈妹纸,小陈给他支了个招:“要不咱改变下思路,别再这么旺季招人淡季辞退了,咱可以开个炸串店,一开始厨房里准备好够大家用的炊具。顾客来了坐在座位上取号排队等餐就好了。炸串店开张了,咱就开始招炸串师父,根据顾客情况,咱预计会招到5个左右。当然啦,你怕一个人忙不过来,也可以一开始在开张前招两三个。这样总比你现买炊具现招人节省时间。”

小朱听了小陈的建议,在夏天来临前,把店开了起来,提供了20张桌子,一开始招了3个炸串师父。顾客络绎不绝,小朱又招了2个炸串师父。如果你有幸路过,一定要去他的店里坐坐,毕竟炸串真的好吃!

盛夏,撸串与啤酒更配的季节,小朱的炸串店顾客来得越来越多,经常坐满了20张桌子,小朱觉得5个炸串师父满负荷运转也忙不过来了,临时招了2个炸串师父来帮忙。但是店就这么大,厨房已经放不下更多炊具了,7个炸串师父依旧搞不定时不时坐满的顾客,小朱没有办法,只能告诉门外想进来吃饭的顾客:“非常抱歉,店里面已经满了,大家要不再外面逛逛再来?或者在旁边等会儿?实在不行先去别家吃,下次早点来?

时间过得很快,天气转冷,顾客量开始减少。临时招来帮忙的师父在连续一周没开工的情况下,也离开了,店里还是5个师父和小陈。小陈想了想,到了冬天顾客更少的时候,要不给师父们放个假吧,等到顾客多了再招回来。

年复一年,日复一日。就这样,小朱的炸串店运转得风生水起。等等,你问小陈妹子?人现在已经是小朱的内人了,生了俩娃,一家人幸福美满地经营着炸串店。

●正经解释

细心的读者肯定已经发现上面的故事中,有很多地方标注了颜色,没错,这些正是对应我们JAVA线程池的工作原理。让我们来正经解释一下。

首先,一个人支摊的阶段,好比程序运行在一个线程。顾客多了,单线程已经处理不及了,自然要开新的线程。但是开新的线程是非常耗费资源的,比如时间,这就好比现招人,现买炊具,现培训。等到任务少了,不需要多个线程了,可以选择关闭线程释放资源,这同样也很耗费时间,就好比故事中小陈要去和师父协商,要赔偿,还要把多的炊具买了。

接下来,小朱开了个炸串店,这里就开始使用到了JAVA线程池的思想了(真怀疑小陈妹子以前是程序媛出身)。

线程池中这么几个重要的参数——

corePoolSize:核心池大小。对应我们故事中的5个炸串师父。值得注意的是,这5个师父并不是一开始就招的(核心线程不是一开始就生成好的)。当然了,我们也可以调用prestartAllCoreThreads()或者prestartCoreThread()方法,一开始就生成好核心线程,对应我们故事中开张前可以招两三个炸串师父。

maximumPoolSize:最大池大小。对应我们故事中的最多容纳的7个炸串师父。多出来了的2个线程是在核心池的基础上新生成的。它们的生成规则是在任务队列(见下)满了之后,也就是我们故事中5个炸串师父忙不过来,店里20张桌子经常坐满,并且池中核心线程已经在使用了的情况下生成的。

workQueueSize:任务队列大小。对应我们故事中的20张桌子,顾客坐下来点餐就餐就是一个任务,而取号排队等参就是加入任务队列,并且在任务队列中等待被线程处理,好比等待炸串师父给烹饪好食物。

keepAliveTime:存活时间。表示线程没有任务执行时最多保持多久时间会终止,对应我们故事中临时招的师父连续一周没开工就离开了的情况。通常这个存活时间仅对非核心线程,也就是临时线程生效。核心线程创建出来后就会一直存在,除非我们调研allowCoreThreadTimeOut(boolean)方法,这对应我们故事中给招的5个师父放个假的情况。

handler:拒绝策略。表示当任务超过了任务队列大小,并且线程池已经达到最大池的大小后对新来的任务采取的拒绝策略,可以是直接抛弃,可以是抛出异常,还可以是自定义策略比如阻塞。这对应我们故事中小朱对门外络绎不绝的顾客所说的三种解决办法。

至此,JAVA线程池最基本最核心的思想和原理就通过一个故事完全解释清楚了。

●继承关系

JAVA提供的线程池相关接口和类的基础关系如下,大家可以有个印象,结合这个图以及上面的故事,大家再去看开头提到的推荐文章会更好。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值