Java 线程池如何知道一个线程的任务已经执行完成
1. 使用 Future
对象
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<?> future = executor.submit(() -> {// 执行任务Thread.sleep(1000);
});// 检查任务是否完成
if (future.isDone()) {System.out.println("任务已完成");
}// 阻塞等待任务完成
try {future.get(); // 等待任务执行完毕
} catch (Exception e) {e.printStackTrace();
}
2. 使用 CompletableFuture
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {// 异步执行任务System.out.println("执行任务");
});// 添加完成回调
future.thenRun(() -> {System.out.println("任务已完成");
});// 等待完成
future.join();
3. 使用 CountDownLatch
CountDownLatch latch = new CountDownLatch(1);executor.execute(() -> {try {// 执行任务System.out.println("执行任务");} finally {latch.countDown(); // 任务完成后计数减一}
});// 等待任务完成
latch.await();
4. 使用 invokeAll
方法
List<Callable<String>> tasks = Arrays.asList(() -> "Task 1 result",() -> "Task 2 result"
);List<Future<String>> futures = executor.invokeAll(tasks);
// invokeAll会等待所有任务完成后再返回
for (Future<String> future : futures) {String result = future.get(); // 获取结果
}
5. 关闭线程池并等待
executor.shutdown();
try {// 等待所有任务在指定时间内完成if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow(); // 强制关闭}
} catch (InterruptedException e) {executor.shutdownNow();
}
线程池通过以下几种机制来知道线程任务已经执行完成:
6. 任务执行状态跟踪
线程池内部维护每个任务的执行状态:
- 当任务提交到线程池时,会创建对应的
Future
对象 Future
对象跟踪任务的执行状态(未开始、运行中、已完成、已取消等)
7. Worker线程生命周期管理
// 线程池内部的Worker机制
class Worker implements Runnable {public void run() {while (task != null || (task = getTask()) != null) {// 执行任务task.run();// 任务执行完成后,继续获取下一个任务}// worker线程结束时,线程池会感知到}
}
8. 主要的检测方式
Future状态检查
- 通过
Future.isDone()
检查任务是否完成 - 通过
Future.get()
阻塞等待任务完成
线程池状态监控
ThreadPoolExecutor.getCompletedTaskCount()
获取已完成任务数ThreadPoolExecutor.getActiveCount()
获取活跃线程数
回调机制
- 使用
CompletableFuture
的thenRun()
、thenAccept()
等方法注册完成回调
9. 任务完成通知
当 Runnable
或 Callable
任务的 run()
或 call()
方法执行完毕后:
- 线程池会自动更新任务状态为完成
- 如果有等待的线程(如调用
Future.get()
),会收到通知并继续执行 - 线程会返回线程池的阻塞队列中等待下一个任务
这种方式让线程池能够精确地跟踪每个任务的执行状态,确保资源的合理管理和任务的正确执行。