Java线程池

说白了,CachedThreadPool就是Java为我们准备的“灵活工作池”。
它专门处理大量短任务,但如果使用不当很容易导致内存爆炸。

我们先来说说最重要的事情。
核心就两个字:懒惰创造。
当没有工作时,线程直接休眠6 0秒,然后消失。
一有工作,他就立刻找一个闲着的。
如果没有足够的空闲时间,则打开一个新线程,但理论上可以在Integer.MAX_VALUE上打开,这听起来不错。
去年我们跑的一个高并发项目中,简单的创建线程就直接把JVM 1 00%拖到了CPU上,造成了直接的滚雪球效应。
用行话来说,这称为雪崩效应。
事实上,前线的一个小小的延误就导致了后线的一切崩溃。
还有一点是它使用SynchronousQueue作为队列,这意味着如果没有线程接收工作,就会打开新的线程。
没有最大限制,因此特别适合短期任务。
例如,当我们去年以 3 000 个级别运行日志分析时,每秒检测到大约 2 00 个新增量。
任务处理速度必须快于发送速度,否则内存会直接爆炸。

一开始我觉得这个泳池很棒,但后来我发现有些不对劲。
当任务提交率突然提升到每秒数万次时,6 0秒的超时机制已经不足以挽救局面。
线程疯狂创建堆内存,最终只能利用JVM OOM机制强制回收。
等等,还有一件事。
在Spring Boot中使用默认的线程池处理异步接口时,很多人没有意识到线程在进入睡眠之前会完成当前的任务。
延迟该过程会减慢响应时间。
我认为调整 keep-alive 参数值得尝试。

简而言之,优先考虑短任务,但需要监控任务量和线程数,并且实际上不要超过理论最大值。

Java线程池溢出了,你的拒绝策略准备好了吗?

线程池溢出的拒绝策略。
核心数 + 最大数 + 队列已满,导致拒绝。
AbortPolicy:引发异常并向系统发出警告。
CallerRunsPolicy:自执行,降低速度。
DiscardPolicy:静默删除,没有影响。
DiscardOldestPolicy:丢弃旧任务并先更新它们。
对于重要的工作使用取消,如果没有丢失则使用呼叫者。
Discard 用于不相关的任务,DiscardOldest 用于删除旧任务。
自定义策略可以记录日志记录或保留操作。
正确的参数配置和策略选择可以防止系统过载。

线程池 Thread Pool , java

1 . newCachedThreadPool():适合下载任务等短期任务。
2 . newFixedThreadPool(2 ):固定2 个线程,适合CPU密集型任务。
3 .提交6 个任务,newCachedThreadPool可以开启所有线程。
4 . run()方法打印线程名称以验证线程重用。
5 . 使用 shutdown+waitTermination() 正常关闭。
6 .无共享资源,无需同步。
7 .我还在验证中,建议先小规模测试一下。

自己掂量一下。