03 | 线程池:业务代码最常用也最容易犯错的组件
该思维导图由 AI 生成,仅供参考
线程池的声明需要手动进行
- 深入了解
- 翻译
- 解释
- 总结
线程池管理是开发中常见但容易出现问题的技术点。本文通过三个生产事故案例,深入探讨了线程池的使用注意事项。首先,强调了使用Executors类提供的快捷方法创建线程池可能导致的问题,建议手动声明线程池并根据实际场景评估核心参数。其次,详细分析了newFixedThreadPool和newCachedThreadPool可能导致的OOM问题,强调了设置有界的工作队列和可控的线程数的重要性。作者还分享了一个实际事故案例,强调了为自定义线程池指定有意义的名称以便排查问题的重要性。最后,建议使用监控手段观察线程池状态,以便提早发现并解决问题。文章内容丰富,包括了线程池的默认工作行为、线程池的复用问题等,对读者在实际应用中遇到的问题提供了解决思路和最佳实践。文章通过生动的案例和详细的分析,提醒读者在使用线程池时要慎之又慎,避免常见的陷阱和问题。
《Java 业务开发常见错误 100 例》,新⼈⾸单¥59
全部留言(73)
- 最新
- 精选
- 蚂蚁内推+v置顶第二个问题大家都说核心线程数不会被回收,但是方法执行完线程池的引用已经引用不到了吧,线程池对象会被垃圾回收吧,垃圾回收时核心线程怎么办呢
作者回复: ThreadPoolExecutor回收不了,可以看看其源码,工作线程Worker是内部类,只要它活着,换句话说线程在跑,就会阻止ThreadPoolExecutor回收,所以其实ThreadPoolExecutor是无法回收的,并不能认为ThreadPoolExecutor没有引用就能回收
2020-03-14728 - Darren置顶第一个问题的来了,请老师指点: https://github.com/y645194203/geektime-java-100/blob/master/ExtremeThreadPoolExecutor.java 里面自定义了一个extremeOffer方法,因为不是BlockQUeue接口的方法,所以在执行拒绝策略后,真正加入阻塞队列的时候强转了一些,感觉不是很好,有没有更好的处理方法,请老师指点下。 加上之前回答的第二个问题答案: 不会被回收,会OOM,即使是自定义线程池,核心线程是不会回收的,每次需要10个线程,刚好是核心线程数,因此每次请求都会创建10个核心线程数的线程池,请求次数多了后,很快就回OOM。 Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
作者回复: 直接用put即可,可以参考这里的回复: https://stackoverflow.com/questions/19528304/how-to-get-the-threadpoolexecutor-to-increase-threads-to-max-before-queueing 不过要考虑选择丢数据还是阻塞 其实,实现自己的RejectedExecutionHandler耦合自己的Queue也无可厚非。Tomcat也是这样的,其实现参考这里:https://github.com/apache/tomcat/blob/a801409b37294c3f3dd5590453fb9580d7e33af2/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java
2020-03-12629 - 观弈道人"我们把 printStats 方法打印出的日志绘制成图表",想问下老师,这个图表咋绘制的,想学习下
作者回复: Excel...
2020-03-1853 - 汝林外史1. 既然选择先扩容线程池再加入队列,那为什么不干脆把核心线程数设置大一些,然后核心线程数可回收这种策略呢? 2. 复用线程池,任务很慢,主线程get结果的时候不会导致主线程卡死的状态吗?不是也提倡不同的任务用不同的线程池,那复用与不复用的边界在哪里呢?是要根据也无需求自己评估吗?
作者回复: 1. 你说的这种策略,此文也有提到: https://stackoverflow.com/questions/19528304/how-to-get-the-threadpoolexecutor-to-increase-threads-to-max-before-queueing 其实,我们希望的是尽量确保有足够多的线程能处理任务,但是又不闲置过多线程,或临时创建过多线程,换句话说让线程的创建和回收不要太频繁。选择哪个策略要根据任务的性质和压力的流量形态来决定。 2. 这里我说的复用线程池是指不每次都创建线程池,线程池必须复用而不是按需创建,但是不推荐一味混用一个线程池。对于选择是否混用线程池,至少对于频+快的任务和少+慢的任务应该分开,还是要根据实际任务的性质来选择。
2020-03-1418 - 陈天柱首先赞一下老师的排查问题的思路!!!然后针对第二个问题,我觉得不会被回收且很快就会OOM了,因为每次请求都新建线程池,每个线程池的核心数都是10, 虽然自定义线程池设置2秒回收,但是没超过线程池核心数10是不会被回收的, 不间断的请求过来导致创建大量线程,最终OOM
作者回复: 👍🏻
2020-03-1249 - CDz1. 线程池过多造成OOM 因为活跃线程过多和线程池不会被回收 2. Java Stream Api异步分流 公用一个默认forkjion线程池,使用时要注意 3. 线程池创建时要分析执行任务是IO资源型还是CPU资源型 4. IO资源型或者说执行较长时间任务,并且拒绝策略为Call时,会在线程池满状态后交给**调用者**线程执行,如果是Web服务跑在tomcat⬆️的话,就导致整体吞吐量下降
作者回复: 总结不错
2020-04-188 - miniluo那JDK提供的四种快捷创建线程池的方式时候没有想到这些坑吗?如果想到了为何还提供这些方便的方式呢?还要麻烦老师解答,谢谢~
作者回复: 提供方便的api这个事情本身没错 使用者自己需要使用api之前详细阅读说明
2020-03-3126 - 程序员小跃看大家的思考题也是一种享受。 线程池这个,记得刚学会编程的时候,面试就问线程池的创建,然后回来看书知道了如何创建各种各样的线程池;但是项目中还是没遇到更多的坑,看了老师的解析,让我以后对线程池的使用更加谨慎了。
作者回复: 的确是享受
2020-03-175 - Darren先回答第二个问题吧,第一个等天亮了,试一试 不会被回收,会OOM,即使是自定义线程池,核心线程是不会回收的,每次需要10个线程,刚好是核心线程数,因此每次请求都会创建10个核心线程数的线程池,请求次数多了后,很快就回OOM。 Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
作者回复: 👍🏻
2020-03-123 - Joker老师会装门写一篇 课后回答的解答来回答这些问题吗?
作者回复: 不会,没必要单独汇总一篇,我的答案也不一定是标准答案,看看大家的讨论不是挺好?
2020-03-252