线程池不关闭引发的OOM血案

又踩坑了系列…

得到反馈管理端一个返回系统基本权限数据的接口服务端异常了。查看错误日志:

竟然是OOM,Java应用程序已达到其可以启动线程数量的极限了。肯定是有地方创建了太多线程,消耗光了系统的线程数。
Caused by: java.lang.OutOfMemoryError: unable to create new native thread

由于线上机器已经漂移重建,无法查看堆栈现场。使用测试环境看下线程数(因为运行情况差不多,在一定情况是可以反应线上环境的)。

竟然有1w多个waiting线程。

然后和同事定位代码。发现问题代码集中在:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public Integer getPermissionCount(Long appId) {
ExecutorService es = Executors.newFixedThreadPool(4);
CompletionService<Integer> cs = new ExecutorCompletionService<>(es);
cs.submit(() -> flagService.getFlagCount(appId));
cs.submit(() -> roleService.getRoleCountByAppId(appId));
cs.submit(() -> featureService.getFeatureCountByAppId(appId));
cs.submit(() -> areaService.getAreaCountByAppId(appId));

Integer result = 0;
for (int i=0; i<4; i++) {
try {
Integer permissionCount = cs.take().get();
result = result + permissionCount;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return result;
}

这里犯了一个致命的问题 – 线程池使用完未关闭。改进修改这个问题,增加线程池关闭:

1
es.shutdown();

如果线程池不关,那线程池是不会自动销毁的。也就是每次调用请求都会创建coreSize个线程,时间久了肯定会造成OOM。

啊 … 我真蠢。


评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×