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() 获取活跃线程数

回调机制

  • 使用 CompletableFuturethenRun()thenAccept() 等方法注册完成回调

9. 任务完成通知

RunnableCallable 任务的 run()call() 方法执行完毕后:

  • 线程池会自动更新任务状态为完成
  • 如果有等待的线程(如调用 Future.get()),会收到通知并继续执行
  • 线程会返回线程池的阻塞队列中等待下一个任务

这种方式让线程池能够精确地跟踪每个任务的执行状态,确保资源的合理管理和任务的正确执行。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐