java线程池bug的一些思考

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

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

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

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

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

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

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

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

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

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

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

相关推荐
贾斯汀玛尔斯8 分钟前
每天学一个算法--LSM-Tree(Log-Structured Merge Tree)
java·算法·lsm-tree
bitt TRES8 分钟前
springboot与springcloud对应版本
java·spring boot·spring cloud
Y0011123623 分钟前
JavaWeb-end
java·servlet·web
bzmK1DTbd1 小时前
Git版本控制:Java项目中的分支管理与合并策略
java·开发语言·git
JWASX3 小时前
【RocketMQ 生产者和消费者】- 事务源码分析(1)
java·rocketmq·java-rocketmq
AlunYegeer4 小时前
JAVA,以后端的视角理解前端。在全栈的路上迈出第一步。
java·开发语言·前端
DFT计算杂谈5 小时前
自动化脚本一键绘制三元化合物相图
java·运维·服务器·开发语言·前端·python·自动化
2301_771717215 小时前
Spring Boot 自动配置核心注解
java·spring boot·mybatis
小Y._5 小时前
面试被问synchronized锁升级,这5个问题答不上来直接挂!
java
姚青&5 小时前
测试技术体系
java·python