Java线程池通过以下几种机制来知道线程任务是否执行完成:
1. Future对象机制(最常用)
ExecutorService executor = Executors.newFixedThreadPool(5);
// 提交任务,返回Future对象
Future<?> future = executor.submit(() -> {
// 任务逻辑
System.out.println("任务执行中...");
Thread.sleep(1000);
return "结果";
});
// 1. 阻塞等待结果
try {
String result = (String) future.get(); // 阻塞直到任务完成
System.out.println("任务完成,结果:" + result);
} catch (Exception e) {
e.printStackTrace();
}
// 2. 非阻塞检查状态
while (!future.isDone()) {
System.out.println("任务还在执行中...");
Thread.sleep(100);
}
System.out.println("任务已完成:" + future.isDone());
2. CompletionService(批量任务监控)
ExecutorService executor = Executors.newFixedThreadPool(5);
CompletionService<String> completionService =
new ExecutorCompletionService<>(executor);
// 提交多个任务
for (int i = 0; i < 5; i++) {
final int taskId = i;
completionService.submit(() -> {
Thread.sleep(taskId * 1000L);
return "任务" + taskId + "完成";
});
}
// 按完成顺序获取结果
for (int i = 0; i < 5; i++) {
Future<String> future = completionService.take(); // 阻塞直到有任务完成
System.out.println(future.get());
}
3. CompletableFuture(Java 8+,推荐)
ExecutorService executor = Executors.newFixedThreadPool(5);
// 异步执行,添加回调
CompletableFuture.supplyAsync(() -> {
System.out.println("任务开始执行...");
Thread.sleep(2000);
return "执行结果";
}, executor).thenAccept(result -> {
// 任务完成后的回调
System.out.println("任务完成,结果:" + result);
}).exceptionally(ex -> {
// 异常处理
System.out.println("任务执行异常:" + ex.getMessage());
return null;
});
// 等待所有任务完成
CompletableFuture<Void> allTasks = CompletableFuture.allOf(
CompletableFuture.runAsync(() -> System.out.println("任务1"), executor),
CompletableFuture.runAsync(() -> System.out.println("任务2"), executor)
);
allTasks.get(); // 阻塞直到所有任务完成
4. 线程池本身的监控方法
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 4, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10)
);
executor.execute(() -> {
System.out.println("任务执行中");
});
// 监控线程池状态
System.out.println("已完成任务数:" + executor.getCompletedTaskCount());
System.out.println("活跃线程数:" + executor.getActiveCount());
System.out.println("队列大小:" + executor.getQueue().size());
5. 同步工具辅助
ExecutorService executor = Executors.newFixedThreadPool(3);
CountDownLatch latch = new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
executor.execute(() -> {
try {
// 执行任务
Thread.sleep(1000);
} finally {
latch.countDown(); // 任务完成,计数器减1
}
});
}
latch.await(); // 阻塞直到计数器为0
System.out.println("所有任务已完成");
executor.shutdown();
6. 自定义线程池扩展
class MonitoringThreadPool extends ThreadPoolExecutor {
public MonitoringThreadPool() {
super(2, 4, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
// 任务执行完成后自动调用
System.out.println("任务执行完成");
if (t != null) {
System.out.println("任务异常:" + t.getMessage());
}
}
}
线程池任务完成的内部机制
- 任务队列管理:线程池维护一个任务队列,工作线程从队列中获取任务执行
- Worker线程循环:每个Worker线程不断从队列中获取任务执行
- Future封装:
submit()方法将任务封装为FutureTask - 状态标记:任务执行完毕后会修改Future的状态
- 结果存储:执行结果存储在Future中,异常被封装
最佳实践建议
- 使用 CompletableFuture 进行异步编程(Java 8+)
- 批量任务使用 CompletionService
- 需要精确控制时使用 CountDownLatch/CyclicBarrier
- 避免在业务代码中轮询检查,尽量使用回调或阻塞等待
- 注意正确处理异常,避免任务静默失败