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

如何等待ThreadPool执行完毕后再启动单线程任务

解决ThreadPool任务完成后再执行单线程任务的问题

嘿,我来帮你搞定这个线程池等待的问题!你现在需要确保10线程的ThreadPool完成所有质数检测任务后,再启动单线程的检测逻辑对吧?之前尝试在PrimeTask里同步方法没用,是因为单个任务的同步没法跟踪整个线程池的任务完成状态,得用专门的同步工具或者线程池本身的API来实现。

下面给你两种最常用的解决方案,结合你的质数检测场景来举例:

方法一:用CountDownLatch跟踪任务完成

CountDownLatch是Java并发包里的工具类,原理是初始化一个计数器,每个任务完成时将计数器减1,主线程等待计数器变为0后再继续执行。

步骤1:改造PrimeTask类

给任务类传入CountDownLatch,任务执行完毕后调用countDown():

class PrimeTask implements Runnable {
    private final int number;
    private final CountDownLatch latch;

    public PrimeTask(int number, CountDownLatch latch) {
        this.number = number;
        this.latch = latch;
    }

    @Override
    public void run() {
        try {
            // 执行你的质数检测逻辑
            boolean isPrime = isPrimeNumber(number);
            // 这里可以记录结果或者做其他处理,比如打印
            System.out.println("ThreadPool检测 " + number + ": " + isPrime);
        } finally {
            // 不管任务成功还是失败,都要确保计数器减1
            latch.countDown();
        }
    }

    // 你的质数检测实现
    private boolean isPrimeNumber(int num) {
        if (num <= 1) return false;
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) return false;
        }
        return true;
    }
}

步骤2:主线程中等待线程池任务完成

在提交所有任务后,调用latch.await()等待,之后再启动单线程任务:

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PrimeCheckerDemo {
    public static void main(String[] args) throws InterruptedException {
        // 初始化10线程的线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        // 假设你要检测的数字列表
        List<Integer> targetNumbers = Arrays.asList(1000003, 1000033, 1000037, 1000039, 1000081);

        // 创建CountDownLatch,计数器值等于任务数量
        CountDownLatch taskLatch = new CountDownLatch(targetNumbers.size());

        // 提交所有质数检测任务到线程池
        for (int num : targetNumbers) {
            threadPool.submit(new PrimeTask(num, taskLatch));
        }

        // 等待所有线程池任务完成
        taskLatch.await();
        // 任务完成后关闭线程池(可选,因为之后不再使用)
        threadPool.shutdown();

        // 现在启动单线程检测任务
        System.out.println("\n=== ThreadPool任务已全部完成,开始单线程检测 ===");
        long singleThreadStartTime = System.currentTimeMillis();
        for (int num : targetNumbers) {
            boolean isPrime = isPrimeNumber(num);
            System.out.println("单线程检测 " + num + ": " + isPrime);
        }
        long singleThreadEndTime = System.currentTimeMillis();
        System.out.println("单线程检测总耗时: " + (singleThreadEndTime - singleThreadStartTime) + "ms");
    }

    // 提取公共的质数检测方法,避免重复代码
    private static boolean isPrimeNumber(int num) {
        if (num <= 1) return false;
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) return false;
        }
        return true;
    }
}

方法二:利用ExecutorService的shutdown()和awaitTermination()

如果你用的是ThreadPoolExecutor(Executors.newFixedThreadPool()返回的其实就是它的实例),可以直接用线程池本身的方法来等待任务完成:

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class PrimeCheckerDemo {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        List<Integer> targetNumbers = Arrays.asList(1000003, 1000033, 1000037, 1000039, 1000081);

        // 提交所有任务
        for (int num : targetNumbers) {
            threadPool.submit(() -> {
                boolean isPrime = isPrimeNumber(num);
                System.out.println("ThreadPool检测 " + num + ": " + isPrime);
            });
        }

        // 关闭线程池,不再接受新任务
        threadPool.shutdown();
        // 等待所有已提交的任务完成,这里设置超时时间(比如1小时),防止无限等待
        if (threadPool.awaitTermination(1, TimeUnit.HOURS)) {
            System.out.println("\n=== ThreadPool任务全部完成 ===");
        } else {
            System.err.println("ThreadPool任务超时未完成,强制终止");
            threadPool.shutdownNow();
        }

        // 启动单线程检测任务
        long singleThreadStartTime = System.currentTimeMillis();
        for (int num : targetNumbers) {
            boolean isPrime = isPrimeNumber(num);
            System.out.println("单线程检测 " + num + ": " + isPrime);
        }
        long singleThreadEndTime = System.currentTimeMillis();
        System.out.println("单线程检测总耗时: " + (singleThreadEndTime - singleThreadStartTime) + "ms");
    }

    private static boolean isPrimeNumber(int num) {
        // 质数检测逻辑
        if (num <= 1) return false;
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) return false;
        }
        return true;
    }
}

为什么之前的同步方法没用?

你之前尝试在PrimeTask里同步某个方法,这种同步只是保证单个任务内部的线程安全,或者同一时间只有一个线程执行该方法,但它没法跟踪所有线程池任务的完成状态。你需要的是一个跨任务的同步机制,让主线程知道所有子任务都已经跑完,这正是CountDownLatch或者ExecutorService终止方法的作用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:54:06