java线程池bug的一些思考

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

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

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

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

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

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

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

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

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

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

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

相关推荐
CodeClimb6 分钟前
【华为OD-E卷-简单的自动曝光 100分(python、java、c++、js、c)】
java·python·华为od
风清云淡_A17 分钟前
【java基础系列】实现数字的首位交换算法
java·算法
Gao_xu_sheng19 分钟前
Java程序打包成exe,无Java环境也能运行
java·开发语言
大卫小东(Sheldon)26 分钟前
Java的HTTP接口测试框架Gatling
java
谢家小布柔28 分钟前
java中的继承
java·开发语言
l1384942745134 分钟前
Java每日一题(2)
java·开发语言·游戏
苹果醋337 分钟前
SpringBoot快速入门
java·运维·spring boot·mysql·nginx
WANGWUSAN661 小时前
Python高频写法总结!
java·linux·开发语言·数据库·经验分享·python·编程
Yvemil71 小时前
《开启微服务之旅:Spring Boot 从入门到实践》(一)
java
forNoWhat1 小时前
java小知识点:比较器
java·开发语言