固定线程池内存泄漏
FixedThreadPool memory leak
我有一个 Stream<String>
并对其项目执行一些操作,包括处理字符串并将其写入文件。
具有以下 groovy 代码,并处理 100 万个项目 我 运行 进入 OutOfMemoryError.
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
stream.forEach { item ->
executorService.execute {
handle(item)
}
}
executorService.shutdown()
executorService.awaitTermination(1, TimeUnit.DAYS)
经过一些分析后,我发现 Runnable 任务不由 gc 处理,并且 在 BlockingQueue 中保持活动状态,直到应用程序失败。
为什么 ExecutorService 将完成的 Runnable 保留在队列中?以及应该如何清理?
内存泄漏是因为 BlockingQueue 被填满的速度比 ExecutorService 从中提取任务快。
这是因为使用 forEach
方法迭代流非常快,但任务需要 运行 一些时间。
这是我应用的解决方案
def processors = Runtime.getRuntime().availableProcessors()
ExecutorService executorService = new ThreadPoolExecutor(
processors, processors,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(1000),
new ThreadPoolExecutor.CallerRunsPolicy()
)
这基本上只是限制 BlockingQueue 的大小,并确保主线程在队列已满时接管工作。
感谢@JBNizet 和其他人在上面的评论中提供的帮助。
我有一个 Stream<String>
并对其项目执行一些操作,包括处理字符串并将其写入文件。
具有以下 groovy 代码,并处理 100 万个项目 我 运行 进入 OutOfMemoryError.
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
stream.forEach { item ->
executorService.execute {
handle(item)
}
}
executorService.shutdown()
executorService.awaitTermination(1, TimeUnit.DAYS)
经过一些分析后,我发现 Runnable 任务不由 gc 处理,并且 在 BlockingQueue 中保持活动状态,直到应用程序失败。
为什么 ExecutorService 将完成的 Runnable 保留在队列中?以及应该如何清理?
内存泄漏是因为 BlockingQueue 被填满的速度比 ExecutorService 从中提取任务快。
这是因为使用 forEach
方法迭代流非常快,但任务需要 运行 一些时间。
这是我应用的解决方案
def processors = Runtime.getRuntime().availableProcessors()
ExecutorService executorService = new ThreadPoolExecutor(
processors, processors,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(1000),
new ThreadPoolExecutor.CallerRunsPolicy()
)
这基本上只是限制 BlockingQueue 的大小,并确保主线程在队列已满时接管工作。
感谢@JBNizet 和其他人在上面的评论中提供的帮助。