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

如何让ThreadPool在有可用线程时提交任务以避免资源耗尽

解决线程池任务无限制堆积的问题

你这段代码的核心问题在于无限制地向线程池提交任务——线程池只有2个工作线程,但你每次循环就提交500个任务,这些未执行的任务会不断积压在线程池的无界队列中,随着循环次数增加,队列占用的内存会越来越大,最终导致程序资源耗尽甚至崩溃。

要实现「仅在线程池有可用线程时才提交任务」的需求,最可靠的方式是用Semaphore(信号量)做流量控制,让提交任务的速度和线程池的处理能力匹配。具体思路如下:

  • 创建一个许可数等于线程池大小的信号量
  • 每次提交任务前,先获取一个信号量许可(没有可用许可时会阻塞,直到有线程空闲)
  • 任务执行完成后,释放对应的许可,让新的任务可以被提交

下面是修改后的完整代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class ControlledTaskSubmission {
    public static void main(String[] args) {
        int threadPoolSize = 2;
        ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
        // 信号量许可数与线程池大小保持一致
        Semaphore taskSemaphore = new Semaphore(threadPoolSize);

        int iteration = 1;
        while (true) {
            for (int i = 0; i < 500; i++) {
                try {
                    // 阻塞等待可用许可,直到有线程释放资源
                    taskSemaphore.acquire();
                    System.out.println("Exec " + iteration + " " + i);
                    executorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                System.out.println("entered");
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            } finally {
                                // 任务执行完毕,必须释放许可,否则会导致信号量耗尽
                                taskSemaphore.release();
                            }
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("Finished iteration " + iteration++);
        }
    }
}

关键细节说明

  • 信号量的acquire()方法会阻塞当前线程,直到获取到可用许可——这就保证了只有线程池有空闲线程时,才会提交新任务
  • 必须在finally块中调用release(),确保即使任务执行抛出异常,许可也能被正确释放,避免信号量被永久占用
  • 这种方式从根源上避免了任务堆积,线程池的队列不会出现大量未执行的任务,内存占用会保持稳定

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 08:17:38