java线程池bug的一些思考

科学需要对前人的怀疑,对权威的怀疑。

但是上学的时候,我们也需要去理解课本。

现在网上充斥了"java 线程池的缺点"这一观点。分析了一下线程池的工作原理,确实也存在这些问题。

Java线程池工作原理。核心线程数,最大线程数,任务队列,当任务超过核心线程数的时候,就会往任务队列里面放,如果超过任务队列数量那么就会增加线程数到最大线程数。然后多个线程继续处理。如果再放进去,就会执行拒绝策略。

"JAVA默认创建的线程池,是一个无限的任务队列,如果在任务数量足够的多情况下,就会OOM"。这是一个bug。

知道了原理,我们还是还原使用场景。

之前自己使用了一次,就是取1000W的数据,然后在对每个文件进行处理。因为涉及到文件处理,我就想使用多线程。数据库我使用的是JPA,然后我就遇到了第一个问题,发现使用Stream<T> 跟自己想象的不一样。造成了大量的GC,最后OOM了。然后就是通过之前JPA 获取大量数据进行处理的。从数据库返回的数据不是全部添加到内存中。

后面的代码就很简单,放到线程池去处理就好了。然后发现,虽然从数据库返回的数据不全部在内存,但是都放到了任务队列里面了。内存还是没有减少。不过没有造成数据再内存里翻倍,(一份是数据库的List,然后还都在任务队列里面有一份,如果任务队列里面的数据和数据库返回的是一致的,应该多出来的是那么多指针。) ps:上诉问题最好的解决方式就是加内存,可以很快的解决问题。通过代码来优化,就比较耗时了。

其实我理想的方式是,我从数据库取100个,然后交给线程池处理,处理了差不多了,在从数据库取一部分。这样就可以大量的减少内存的使用,只不过发现这种很复杂。感觉有些和reactive差不多的感觉。

还有一种我想到的线程池使用的大量场景就是任务接受。不停的给服务器发送任务。造成了任务队列边长,消化不完造成OOM。其实我觉得这种解决方式是增加新的pod,而不是修改任务队列的固定长度,最后通过拒绝策略拒绝掉。或者通过限流,来控制任务的来源,把处理不了的任务,拒绝在最前端,而不是直接交给后面的线程池直接处理。那样就算你只用固定长度的任务队列,还是会执行拒绝策略,那么你还得处理被拒绝的任务。

最后就想说,不是屈服JDK的权威,说他们设计的有问题。我觉得所有的观点都有道理,具体问题具体分析吧。不要只有一个声音就好。

相关推荐
长河39 分钟前
Java开发者LLM实战——LangChain4j最新版教学知识库实战
java·开发语言
Cyan_RA91 小时前
SpringMVC @RequestMapping的使用演示和细节 详解
java·开发语言·后端·spring·mvc·ssm·springmvc
喵手3 小时前
玩转Java网络编程:基于Socket的服务器和客户端开发!
java·服务器·网络
再见晴天*_*4 小时前
SpringBoot 中单独一个类中运行main方法报错:找不到或无法加载主类
java·开发语言·intellij idea
hdsoft_huge7 小时前
Java & Spring Boot常见异常全解析:原因、危害、处理与防范
java·开发语言·spring boot
雨白8 小时前
Java 多线程指南:从基础用法到线程安全
android·java
Hungry_Shark8 小时前
IDEA版本控制管理之使用Gitee
java·gitee·intellij-idea
赛姐在努力.8 小时前
《IDEA 突然“三无”?三秒找回消失的绿色启动键、主菜单和项目树!》
java·intellij-idea
猎板PCB黄浩8 小时前
从废料到碳减排:猎板 PCB 埋容埋阻的绿色制造革命,如何实现环保与性能双赢
java·服务器·制造
ZzzK,8 小时前
JAVA虚拟机(JVM)
java·linux·jvm