线程池通过多种机制来判断一个线程的任务是否已经执行完成。让我们深入探讨这个问题:
- Runnable 接口
当使用 Runnable 接口时,线程池通过 run() 方法的执行完成来判断任务是否结束。
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(new Runnable() {
@Override
public void run() {
// 任务逻辑
System.out.println("Task completed");
}
});
在这种情况下,当 run() 方法执行完毕,线程池就认为任务已经完成。
- Callable 接口和 Future 对象
使用 Callable 接口时,线程池可以通过 Future 对象来判断任务是否完成。
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
// 任务逻辑
return "Task result";
}
});
// 检查任务是否完成
if (future.isDone()) {
System.out.println("Task is completed");
}
- 任务完成回调
使用 CompletableFuture 可以设置任务完成的回调。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 任务逻辑
return "Task result";
}, executor);
future.thenAccept(result -> {
System.out.println("Task completed with result: " + result);
});
- 线程池内部机制
线程池内部使用工作线程(Worker)来执行任务。每个 Worker 在执行完一个任务后,会尝试从任务队列中获取下一个任务。如果没有新任务,Worker 会进入等待状态。
// ThreadPoolExecutor 内部的 Worker 类(简化版)
private final class Worker implements Runnable {
public void run() {
try {
while (task != null || (task = getTask()) != null) {
runTask(task);
}
} finally {
workerDone(this);
}
}
}
- 任务计数
ThreadPoolExecutor 维护了一个 completedTaskCount,用于记录已完成的任务数。
public class ThreadPoolExecutor extends AbstractExecutorService {
private long completedTaskCount;
// 当任务完成时,会调用这个方法
void afterExecute(Runnable r, Throwable t) {
completedTaskCount++;
}
}
- 自定义 ThreadFactory
可以通过自定义 ThreadFactory 来创建能够报告任务完成状态的线程。
class CustomThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
return new Thread(r) {
@Override
public void run() {
super.run();
System.out.println("Task in thread " + getName() + " completed");
}
};
}
}
ExecutorService executor = Executors.newFixedThreadPool(2, new CustomThreadFactory());
- 使用 CountDownLatch 或 CyclicBarrier
对于需要等待多个任务完成的场景,可以使用 CountDownLatch 或 CyclicBarrier。
int taskCount = 3;
CountDownLatch latch = new CountDownLatch(taskCount);
for (int i = 0; i < taskCount; i++) {
executor.execute(() -> {
// 任务逻辑
latch.countDown();
});
}
latch.await(); // 等待所有任务完成
System.out.println("All tasks completed");
- 定期检查活跃线程数
可以定期检查线程池的活跃线程数来判断是否所有任务都已完成。
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
while (executor.getActiveCount() > 0) {
Thread.sleep(100); // 等待 100 毫秒
}
System.out.println("All tasks completed");
总结:
线程池通过多种机制来跟踪任务的完成状态:
- Runnable 的 run() 方法执行完毕
- Callable 和 Future 的状态
- CompletableFuture 的回调
- 线程池内部的 Worker 机制
- 任务计数器
- 自定义 ThreadFactory
- 同步工具类(如 CountDownLatch)
- 活跃线程数检查
选择哪种方法取决于具体的应用场景和需求。在实际应用中,可能需要结合多种方法来准确跟踪任务的完成状态。