MST

星途 面试题库

面试题:Java异步编程中的CompletableFuture的复杂应用

假设你有多个异步任务,任务1完成后根据其结果决定是否执行任务2,任务3和任务4并行执行且它们完成后再执行任务5。请使用CompletableFuture实现该场景,并阐述如何处理任务执行过程中的异常。
11.8万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

以下是使用CompletableFuture实现该场景的代码示例:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class AsyncTasksExample {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            // 模拟任务1
            System.out.println("任务1开始执行");
            // 假设这里有具体的业务逻辑并返回结果
            return "任务1的结果";
        })
       .thenApplyAsync(result -> {
            // 根据任务1的结果决定是否执行任务2
            if ("任务1的结果".equals(result)) {
                System.out.println("任务2开始执行");
                // 假设这里有具体的业务逻辑并返回结果
                return "任务2的结果";
            } else {
                return null;
            }
        })
       .thenAcceptAsync(result -> {
            if (result != null) {
                System.out.println("任务2执行完成,结果: " + result);
            } else {
                System.out.println("根据任务1结果,任务2不执行");
            }
        });

        CompletableFuture<String> task3 = CompletableFuture.supplyAsync(() -> {
            // 模拟任务3
            System.out.println("任务3开始执行");
            // 假设这里有具体的业务逻辑并返回结果
            return "任务3的结果";
        });

        CompletableFuture<String> task4 = CompletableFuture.supplyAsync(() -> {
            // 模拟任务4
            System.out.println("任务4开始执行");
            // 假设这里有具体的业务逻辑并返回结果
            return "任务4的结果";
        });

        CompletableFuture.allOf(task3, task4)
       .thenRunAsync(() -> {
            try {
                String result3 = task3.get();
                String result4 = task4.get();
                System.out.println("任务3和任务4都执行完成,任务3结果: " + result3 + ",任务4结果: " + result4);
                // 任务5开始执行
                System.out.println("任务5开始执行");
                // 假设这里有具体的业务逻辑
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
    }
}

异常处理

  1. thenApplyAsyncthenAcceptAsync等方法:这些方法在任务链中传递异常。如果前一个CompletableFuture任务抛出异常,后续依赖它的任务将不会执行,并且异常会被传递到链尾。可以通过exceptionally方法来捕获异常并处理。例如:
CompletableFuture.supplyAsync(() -> {
    // 模拟任务1可能抛出异常
    if (Math.random() > 0.5) {
        throw new RuntimeException("任务1异常");
    }
    return "任务1的结果";
})
.exceptionally(ex -> {
    System.out.println("捕获到任务1的异常: " + ex.getMessage());
    return null;
})
.thenApplyAsync(result -> {
    if (result != null) {
        // 任务2执行逻辑
        return "任务2的结果";
    }
    return null;
});
  1. CompletableFuture.allOfallOf方法等待所有给定的CompletableFuture完成。如果其中任何一个CompletableFuture抛出异常,allOf返回的CompletableFuture也会完成并带有该异常。可以在thenRunAsync中通过try-catch块捕获异常,如上述代码示例中对任务3和任务4完成后执行任务5的异常处理。或者也可以在allOf返回的CompletableFuture上使用exceptionally方法来处理异常。例如:
CompletableFuture<String> task3 = CompletableFuture.supplyAsync(() -> {
    // 模拟任务3可能抛出异常
    if (Math.random() > 0.5) {
        throw new RuntimeException("任务3异常");
    }
    return "任务3的结果";
});

CompletableFuture<String> task4 = CompletableFuture.supplyAsync(() -> {
    // 模拟任务4可能抛出异常
    if (Math.random() > 0.5) {
        throw new RuntimeException("任务4异常");
    }
    return "任务4的结果";
});

CompletableFuture.allOf(task3, task4)
.exceptionally(ex -> {
    System.out.println("捕获到任务3或任务4的异常: " + ex.getMessage());
    return null;
})
.thenRunAsync(() -> {
    // 任务5执行逻辑
});