34 | Worker Thread模式:如何避免重复创建线程?
王宝令
该思维导图由 AI 生成,仅供参考
在上一篇文章中,我们介绍了一种最简单的分工模式——Thread-Per-Message 模式,对应到现实世界,其实就是委托代办。这种分工模式如果用 Java Thread 实现,频繁地创建、销毁线程非常影响性能,同时无限制地创建线程还可能导致 OOM,所以在 Java 领域使用场景就受限了。
要想有效避免线程的频繁创建、销毁以及 OOM 问题,就不得不提今天我们要细聊的,也是 Java 领域使用最多的 Worker Thread 模式。
Worker Thread 模式及其实现
Worker Thread 模式可以类比现实世界里车间的工作模式:车间里的工人,有活儿了,大家一起干,没活儿了就聊聊天等着。你可以参考下面的示意图来理解,Worker Thread 模式中 Worker Thread 对应到现实世界里,其实指的就是车间里的工人。不过这里需要注意的是,车间里的工人数量往往是确定的。
车间工作示意图
那在编程领域该如何模拟车间的这种工作模式呢?或者说如何去实现 Worker Thread 模式呢?通过上面的图,你很容易就能想到用阻塞队列做任务池,然后创建固定数量的线程消费阻塞队列中的任务。其实你仔细想会发现,这个方案就是 Java 语言提供的线程池。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
Worker Thread模式是解决线程频繁创建、销毁以及OOM问题的有效方案。它类比于现实世界中车间的工作模式,通过创建固定数量的线程来消费阻塞队列中的任务,从而避免了线程频繁创建、销毁的问题。在Java领域,线程池是实现Worker Thread模式的最佳选择,它能够避免无限制地创建线程导致OOM,并且能够限制线程的最大数量。 正确创建线程池的方法包括使用有界队列来接收任务、指明拒绝策略以及为线程赋予业务相关的名字。此外,文章还强调了避免线程死锁的重要性,特别是在存在任务依赖关系的情况下,建议为不同的任务创建不同的线程池。 总的来说,Worker Thread模式能够有效解决线程频繁创建、销毁以及OOM问题,而线程池是实现该模式的重要工具。然而,在使用线程池时,需要格外谨慎,包括正确创建线程池、避免线程死锁问题以及处理任务异常等方面需要引起重视。 小灰同学的代码存在问题,因为他在任务中再次提交了任务给线程池,可能导致死锁或其他问题。正确的做法是直接打印字符串“QQ”而不是再次提交任务给线程池。 总的来说,本文介绍了Worker Thread模式及线程池的重要性和正确使用方法,对于需要解决线程频繁创建、销毁以及OOM问题的开发人员具有重要参考价值。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 并发编程实战》,新⼈⾸单¥59
《Java 并发编程实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(40)
- 最新
- 精选
- vector工厂里只有一个工人,他的工作就是同步的等待工厂里其他人给他提供东西,然而并没有其他人,他将等到天荒地老,海枯石烂~
作者回复: 比喻很形象👍
2019-05-16103 - 曾轼麟EagerThreadPool 老师这个线程池可以避免死锁的情况,死锁的时候会自动撑大
作者回复: 👍👍
2019-05-23265 - Geek_42f729看了一遍评论,有一部分同学回答了课后思考的结论,但是没有描述产生该结论的原因,我来描述一下吧,有不对的地方还请老师、同学们指出; 结论是:小灰写的代码会被一直阻塞; 原因是: 1. 通过Executors.newSingleThreadExecutor()创建的线程池默认是1个核心线程 + 无界工作队列; 2. 第一次submit时,会把池中唯一的一个核心线程给占用; 3. 第二次submit时,由于没有空闲的线程,并且工作队列也没满,所以线程池会把提交的任务添加到工作队列,然后等待空闲线程来执行该任务; 4. 在第二次submit时使用了.get()方法,这里会一直等到线程返回执行结果; 5. 由于两次submit是嵌套执行的,并且此时线程池中也没有空闲线程,所以第二次submit的任务永远不会被执行,.get()方法会就被永远阻塞,从而导致第一次submit的线程也被永远阻塞。
作者回复: 分析很到位
2022-03-18219 - zero感觉这程序会调用栈内存溢出,这段代码相当于无限的递归调用啊。不知道理解的对不对,请老师指点。
作者回复: 不是递归,但会死锁
2019-05-1815 - 木刻希望老师能开一栏专门讲一讲Linux下多线程并发情况下程序性能的排查和调优。谢谢老师
作者回复: 好累😂
2019-05-179 - ack老师,请教个问题,线程死锁那个代码,是活锁吗,思考题我也认为是活锁
作者回复: 我觉得是死锁,活锁有释放再获取的过程
2019-05-166 - Mr_杨老师请教个问题,如果不同业务用不同线程池,保证不了线程数量,会带来并发线程过大,如何控制频繁上下文切换的问题
作者回复: 无解,必须控制线程数量。
2019-11-072 - 王成最近工作中遇到一个关于线程池的问题,莫名其妙的线程就不在执行 问题的原因是 每个线程都会去请求一次http,但是时间长了会出现阻塞现象(http工具类写的有点问题) 最终解决方案,除了优化工具类,还给每一个线程设置了超时时间
作者回复: 设置超时绝对是最佳实践,否则必然出事
2021-07-071 - 张申傲越来越发现,软件领域中的很多问题,都可以向现实世界寻求答案。
作者回复: 一般人解决问题都是以现实世界模型为主的
2021-03-221 - Monday本篇就是一个主题,java创建线程池,并特别注意 1、生产中拒绝使用Executors提供的初始化线程池的方法(因为使用无解队列) 2、生产环境应根据业务自定义拒绝策略
作者回复: ������������
2020-12-203
收起评论