You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FixedThreadPool时内存持续增长的问题排查

解决Executors.newFixedThreadPool()内存持续飙升问题

问题分析

你遇到的内存耗尽问题,核心原因是未清理已处理完成的Future对象引用:

  • 代码中futures列表在循环外部声明,每次while(true)循环都会向其中添加7个新的Future实例;
  • 调用future.get()获取结果后,这些Future(以及关联的FutureTask、Lambda对象、队列节点)仍然被futures列表强引用,垃圾回收器无法回收它们;
  • 随着循环持续执行,列表中的对象数量不断累积,最终导致堆内存耗尽。

即使手动调用System.gc(),由于futures列表还持有强引用,GC只能回收少量临时对象,无法释放Future相关的核心内存,因此内存仍会缓慢增长。堆转储中出现的5万多个FutureTask、LinkedBlockingQueueNode及Lambda对象,正是被futures列表长期引用的结果。

解决方案

将futures列表的声明移至while循环内部,让每次循环产生的Future集合在当前循环结束后失去引用,从而被GC自动回收:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ExecutorServiceTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        int threadCount = 7;

        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
        while (true) {
            // 每次循环创建新的列表,旧列表无引用后会被GC回收
            List<Future<Integer>> futures = new ArrayList<>();
            for (int i = 0; i < threadCount; i++) {
                int finalI = i;
                futures.add(executorService.submit(() -> {
                    try {
                        Thread.sleep(8000);
                        return finalI;
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }));
            }

            for (Future<Integer> future : futures) {
                System.out.println("Value: " + future.get());
            }
        }
    }
}

额外说明

  • 无需手动调用System.gc():JVM的GC机制会自动处理失去引用的对象,手动调用GC不仅无法解决核心引用问题,还会影响性能;
  • 若不需要批量处理结果,也可以在提交任务后直接调用get(),无需存储Future集合,进一步减少内存占用;
  • 长期运行的线程池建议使用ThreadPoolExecutor的自定义配置,监控队列长度和线程状态,避免类似内存泄漏问题。

内容的提问来源于stack exchange,提问作者Dioswison

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 11:46:05