线程池内存溢出
线程池内存溢出
场景
模拟处理 200万的数据,任务处理时间大概 2s
1 | ExecutorService executorService = Executors.newFixedThreadPool(50); |
1 | -Xmx50m -Xms50m -XX:G1HeapRegionSize=2m -XX:MetaspaceSize=128m --PrintGcDetails -XX:MaxMetaspaceSize=128m -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError |
结果
线程处理任务太慢,任务被添加到无界队列,超出虚拟机的堆的最大值。
1 | Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "pool-1-thread-7" |
处理
- 修改线程池大小,加快处理流程 – 可能 cpu 处理不过来,可能随着任务量的增长,还是可能出现内存溢出
- 降低任务添加频率 添加任务的时候休眠,这样做的问题还是没办法保证一定不会出现异常,并且还人为限制了 cpu 的处理效率
1
2
3
4
5
6
7
8
9
10
11
12
13
14ExecutorService executorService = Executors.newFixedThreadPool(50);
for (int i = 0; i < 2000000; i++) {
executorService.execute(() -> {
try {
log.info("thread:{},begin:{}", Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(2);
log.info("thread:{},begin:{}", Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
});
TimeUnit.SECONDS.sleep(1);
} - 修改线程池的创建,自定义线程池 自定义的最大等待队列为 1000,并且修改为自定义拒绝策略为,如果队列满了,就阻塞添加任务。
1
2
3
4
5
6
7
8
9
10ExecutorService executorService = new ThreadPoolExecutor(50, 100,
60l, TimeUnit.MINUTES, new ArrayBlockingQueue(1000), (r, executor) -> {
if (!executor.isShutdown()) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 zeofuns!