java 实现等待多个子任务完成后,继续执行主流程

在Java中,可以使用CountDownLatch或者CompletableFuture来等待多个子任务完成后,继续执行主流程。

一、基本实现

1、使用CountDownLatch的实现

import java.util.concurrent.CountDownLatch;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        int taskNum = 5;
        CountDownLatch countDownLatch = new CountDownLatch(taskNum);

        for (int i = 0; i < taskNum; i++) {
            new Thread(() -> {
                try {
                    // 子任务的执行代码
                    // ...

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    // 完成一个子任务,计数器减1
                    countDownLatch.countDown();
                }
            }).start();
        }

        // 等待所有子任务完成
        countDownLatch.await();

        // 所有子任务完成后,继续执行主流程
        // ...
    }
}

在上面的CountDownLatch的示例代码中,如果子任务执行过程中抛出异常,主线程并不能立即感知,因此需要在子任务中进行异常处理,否则主线程可能会一直等待。

2、使用CompletableFuture实现

1)带返回值

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        List> futures = Stream.of(1, 2, 3, 4, 5)
                .map(i -> CompletableFuture.supplyAsync(() -> {
                    try {
                        // 子任务的执行代码,返回一个字符串结果
                        // ...

                    } catch (Exception e) {
                        // 处理子任务执行过程中的异常
                        e.printStackTrace();
                        return null; // 返回null表示子任务执行失败
                    }

                    return "Result " + i;
                }))
                .collect(Collectors.toList());

        // 等待所有子任务完成并获取结果
        List results = futures.stream()
                .map(CompletableFuture::join)
                .filter(result -> result != null)
                .collect(Collectors.toList());

        // 所有子任务完成后,继续执行主流程
        // ...
    }
}

2)不带返回值

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        List> futures = Stream.of(1, 2, 3, 4, 5)
                .map(i -> CompletableFuture.runAsync(() -> {
                     try {
                        // 子任务的执行代码,返回一个字符串结果
                        // ...

                    } catch (Exception e) {
                        // 处理子任务执行过程中的异常
                        e.printStackTrace();
                       // ...
                    }
                }))
                .collect(Collectors.toList());

        // 等待所有子任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

        // 所有子任务完成后,继续执行主流程
        // ...
    }
}

在上面的CompletableFuture示例代码中,如果子任务执行过程中抛出异常,主线程并不能立即感知,因此需要在子任务中进行异常处理,否则主线程可能会一直等待。

二、CompletableFuture超时处理

CompletableFuture是一个基于Future和CompletionStage的异步编程框架,可以让开发者通过简单的API来组合多个异步任务,实现更加灵活和高效的异步编程方式。CompletableFuture还支持异常处理、超时等特性,能够帮助开发者更好地处理复杂的异步场景。

1、代码实现

import java.time.Duration;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Duration timeout = Duration.ofSeconds(5);
        List> futures = Stream.of(1, 2, 3, 4, 5)
                .map(i -> CompletableFuture.supplyAsync(() -> {
                    try {
                        // 子任务的执行代码,返回一个字符串结果
                        // ...

                    } catch (Exception e) {
                        // 处理子任务执行过程中的异常
                        e.printStackTrace();
                        return null; // 返回null表示子任务执行失败
                    }

                    return "Result " + i;
                }))
                .collect(Collectors.toList());

        // 等待所有子任务完成并获取结果
        List results = futures.stream()
                .map(future -> {
                    try {
                        return future.get(timeout.toMillis(), java.util.concurrent.TimeUnit.MILLISECONDS);
                    } catch (InterruptedException | ExecutionException | TimeoutException e) {
                        // 处理子任务执行过程中的异常或超时
                        e.printStackTrace();
                        future.cancel(true); // 取消未完成的子任务
                        return null; // 返回null表示子任务执行失败
                    }
                })
                .filter(result -> result != null)
                .collect(Collectors.toList());

        // 所有子任务完成后,继续执行主流程
        // ...
    }
}

2、Stream.of(1, 2, 3, 4, 5) 是必须得么?是否可以替换?

在上面的示例代码中,Stream.of(1, 2, 3, 4, 5)这行代码并不是必须的,它只是为了演示使用StreamAPI创建CompletableFuture对象的一种方式。在实际开发中,你可能会有不同的方式来创建CompletableFuture对象,例如通过调用其他方法、读取文件、调用远程接口等方式。

Stream.of()方法是用来创建一个由指定元素组成的顺序流的。在这里,我们使用Stream.of(1, 2, 3, 4, 5)来创建一个包含整数1到5的顺序流,然后对这个流使用map()方法来将每个整数转换为一个CompletableFuture对象,最终通过collect()方法将所有CompletableFuture对象收集到一个列表中。

如果你有其他的方式来创建CompletableFuture对象,可以根据实际情况使用不同的方法来创建,而不必一定使用Stream.of()方法。CompletableFuture对象可以通过多种方式创建,例如使用CompletableFuture.supplyAsync()方法创建、使用CompletableFuture.runAsync()方法创建、使用CompletableFuture.completedFuture()方法创建等等,具体取决于你的业务需求。

你可能感兴趣的:(java 实现等待多个子任务完成后,继续执行主流程)