又踩坑了系列…
得到反馈管理端一个返回系统基本权限数据的接口服务端异常了。查看错误日志:
竟然是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; }
|
这里犯了一个致命的问题 – 线程池使用完未关闭。改进修改这个问题,增加线程池关闭:
如果线程池不关,那线程池是不会自动销毁的。也就是每次调用请求都会创建coreSize个线程,时间久了肯定会造成OOM。
啊 … 我真蠢。