Java ExecutorService 如何判断活动中的线程已完成

在编写多线程应用程序时,我们经常会使用Java的ExecutorService来管理并发任务。ExecutorService提供了一种管理线程池的方式,可以方便地提交多个任务并且获取它们的结果。

然而,当我们提交多个任务给ExecutorService后,我们如何才能知道这些任务是否已经完成了呢?本文将介绍几种方法来判断ExecutorService中的线程是否已完成,并提供对应的代码示例。

1. 使用Future来判断任务是否完成

ExecutorService的submit方法可以用来提交一个Callable或者Runnable的任务,并返回一个Future对象。通过Future对象,我们可以判断任务是否已经完成,并且可以获取任务的执行结果。

下面是一个使用Future来判断任务是否完成的示例代码:

import java.util.concurrent.*;

public class ExecutorServiceExample {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        
        Future<String> future1 = executorService.submit(new Task());
        Future<String> future2 = executorService.submit(new Task());
        Future<String> future3 = executorService.submit(new Task());
        
        // 判断任务是否完成
        while (!future1.isDone() || !future2.isDone() || !future3.isDone()) {
            Thread.sleep(1000);
            System.out.println("任务还没有完成,等待1秒钟...");
        }
        
        // 获取任务的执行结果
        String result1 = future1.get();
        String result2 = future2.get();
        String result3 = future3.get();
        
        System.out.println("任务1的执行结果:" + result1);
        System.out.println("任务2的执行结果:" + result2);
        System.out.println("任务3的执行结果:" + result3);
        
        executorService.shutdown();
    }
    
    static class Task implements Callable<String> {
        @Override
        public String call() throws Exception {
            // 模拟任务执行时间
            Thread.sleep(5000);
            return "任务执行完成";
        }
    }
}

上述代码中,我们使用了一个ExecutorService来创建一个线程池,然后通过submit方法来提交任务。每个提交的任务都会返回一个Future对象,我们通过调用isDone方法来判断任务是否已经完成,然后通过get方法来获取任务的执行结果。

2. 使用CompletionService来判断任务是否完成

除了使用Future来判断任务是否完成外,我们还可以使用CompletionService来管理并发任务的执行结果。CompletionService是一个接口,它提供了一种将任务执行结果按照完成顺序组织起来的方式。

下面是一个使用CompletionService来判断任务是否完成的示例代码:

import java.util.concurrent.*;

public class ExecutorServiceExample {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        CompletionService<String> completionService = new ExecutorCompletionService<>(executorService);
        
        completionService.submit(new Task());
        completionService.submit(new Task());
        completionService.submit(new Task());
        
        int completedTasks = 0;
        
        // 判断任务是否完成
        while (completedTasks < 3) {
            Future<String> future = completionService.poll();
            
            if (future != null && future.isDone()) {
                String result = future.get();
                System.out.println("任务的执行结果:" + result);
                completedTasks++;
            } else {
                Thread.sleep(1000);
                System.out.println("任务还没有完成,等待1秒钟...");
            }
        }
        
        executorService.shutdown();
    }
    
    static class Task implements Callable<String> {
        @Override
        public String call() throws Exception {
            // 模拟任务执行时间
            Thread.sleep(5000);
            return "任务执行完成";
        }
    }
}

在上述代码中,我们使用了一个CompletionService来管理任务的执行结果。通过调用completionService.submit方法来提交任务,然后通过调用completionService.poll方法来获取已完成的任务,如果任务已经完成,我们就可以通过调用Future对象的get方法来获取任务的执行结果。

3. 使用CountDownLatch来判断任务是否完成

除了使用Future和CompletionService来判断任务是否完成外,我们还可以使用CountDownLatch来实现同样的功能。CountDownLatch是一个同步工具类,它可以让一个或多个线程等待其他线程完成后再继续执行。

下面是一个使用CountDownLatch来判断任务是否完成的示例代码:

import java.util.concurrent.*;

public class ExecutorServiceExample {

    public static void main(String[] args) throws InterruptedException {
        Executor