当前位置: 首页 > 原理解释

线程池工作原理-线程池工作原理解

最近手头多了几个面试组里的同行,要么在群里吐槽代码忒慢,要么指着代码问为啥线程会卡住。
实际上这些难题的核心,归根结底就是线程池那套“排队干活”的机制。咱们不用去翻开那本几页厚的书,也不用管那些术语如何定义,就盯着代码里的实例对象看看,你会发现这玩意儿实际上就代表了工厂。 线程池说白了就是个“许愿池”要么“修鞋匠”。对象类要是想借作业,先得去申请一个空闲的线程去干。
你想想,要是每次干活完了直接让那个线程去干别的,那线程岂不是连饭都吃不上,随时会崩?线程池就是给你留好了几个“床位”,让对象能反复去申请。申请成功了,线程就活下来了,干完活了直接回来吐出一堆垃圾值,接着被新对象申请。
这就好比你是去图书馆还书,书写完了还得放回架子上持续借,你总不能每次玩完游戏就把座位空了,等着下一局再来吧? 这种机制的核心是为了避免线程的频繁创建和销毁。Java 里的线程创建销毁成本实际上挺高的,对象多了,GC 也得跟着忙,CPU 得分担一下。线程池就把这些开销给压下来了。
比如你看一下这个计数器,线程池里原本只有 100 个线程,要是业务量略微大了一点,对象突然想申请 110 个,那新来的 10 个根本借不到位,就得等到原来的 100 个干完事了,才能腾出 10 个新空位。
这就是“新来的等待,旧的去干活”,效率自然就上去了。 再讲讲那个任务队列,你猜是啥样子?妥妥的公平性、按顺序来。对象一直从队头拿任务,任务队是循环的、有状态的。
这个队列最大的益处就是保证并发保险。
要是你直接想把任务塞到线程里,那线程一多,任务可能就去重了,要么乱跑。用线程池,任务就是一个个踢进队列,线程再一个个踢出队列。队列本身就不能被阻塞,线程也不会出于匹配就卡住。
这就好比排长队,每个人都在等,但绝不会有人出于插队就当场爆雷。 不过话说回来,这个“池”还是有点悬的。线程是活的,不是死的。
要是对象频繁地创建和销毁,那线程池里的那些空闲线程就会变成“僵尸”,干啥也干不了,白白占了 CPU 的工夫。
故此线程池不只是个好办的容器,它也是一套重量级的事务管理器。
比如你设置了“空闲线程超时”,如何设?一般设定为“空闲工夫超过 2 秒,线程自动回收”。
这时候不管对象是不是想用了,只要线程在池里超过 2 秒没干活要么没提交结局,线程就自动回滚了。 举个具体的例子,咱们假设一个在线下单的系统。每来一个用户,线程池里就会多出一个线程去处理他的请求,任务被放入队列,线程启动执行。
这个线程干着干着发现,用户这次没下单,任务也回了。
这 2 秒那会儿了,线程就自动去世了,线程池里少了一个,瞬间多了一个空位。
这时候新的用户来了,又去申请,秒就被塞进去了。
这就保证了,哪怕业务量突然翻倍,也不至于让线程池瞬间塞满了,反而是出于任务处理完及时释放,系统一直能跑得快。 实际上说到底,线程池就是个缓冲器。它把原本线性、有风险的创建销毁循环,给变成了解耦的、循环的队列操作。它不是让你去“创造”线程,而是让你“重用”线程。
只要业务量平稳,线程池就是个稳当的放大器;要是业务量暴增,线程池的吞吐量也会跟着爆表,这时候你可能就得寻思要不要扩容,要么是不是队列调大了。 最终再捋一捋,线程池的精髓就在于“复用”。它不是刚性的,是弹性的。新任务来了,找空闲;空闲没了,新任务就等。它把核心资源的浪费降到最低,把并发性能最大化。
这就是为啥大厂的大线程数都那么高大上的缘由,不是随意刷几个,是有数据支撑的。
故此,下次要是面试问到线程池,你能够不用背那些定义,就顺着这个“许愿池”和“排队”的逻辑,把代码里的实例对象和队列关系说清楚就行。
相关标签:

猜你喜欢

热门阅读

  • 赖柴尔定理-赖柴尔定理
  • 迪拜哪个国家的城市?-迪拜在哪国城市
  • 李毅吧番号及出处-李毅吧番号及出处
  • 贴春联的由来简介50字-春联由来简述
  • 思乡的名言和出处-思乡名言及出处

其他分站