java - 修复ThreadPool内存泄漏

标签 java multithreading groovy memory-leaks threadpoolexecutor

我有一个Stream<String>并对其项目执行一些操作,其中包括处理字符串并将其写入文件。

使用以下常规代码并处理100万个项目,我遇到了OutOfMemoryError

ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())

stream.forEach { item ->
    executorService.execute {
        handle(item)
    }
}

executorService.shutdown()
executorService.awaitTermination(1, TimeUnit.DAYS)

经过一些分析,我发现可运行任务不由 gc 处理,并且在 BlockingQueue 中保持 Activity 状态,直到应用程序失败。

为什么 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 和其他人在上述评论中提供的帮助。

关于java - 修复ThreadPool内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44893217/

相关文章:

java - 尝试连接到 FireStore 数据库但收到 "Program type already present: okio.Buffer$2"

java - 如何重置默认启动器/主屏幕替换?

c++ - VC++ 和 GCC 下 boost::condition_variable 的不同行为

wpf - 如何处理跨线程访问异常?

java - 如何使用 Get 请求专门处理 REST API 中的保留字符,例如值 M&S

Java for 循环与 char 数组 dis-function

java Graphics2D - 生成动态图像

java - 如何暂停 main()

android - 如何在Android的build.gradle的预构建中执行.app程序(文件)

Jenkins 管道 sh 添加新行