如何等待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
相关产品推荐
相关产品推荐

