MST
星途 面试题库

面试题:Java中CompletableFuture异步任务结果传递:复杂链式调用及异常处理

假设有一系列异步任务,第一个任务CompletableFuture<String> task1返回一个字符串,第二个任务需要将该字符串解析为整数(假设解析可能失败),第三个任务将这个整数平方。如果在解析或平方过程中出现异常,需要捕获并返回一个默认值 -1。请用代码展示如何通过CompletableFuture的链式调用完成上述功能,详细说明每一步链式调用方法的意义以及异常处理机制。
13.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
import java.util.concurrent.CompletableFuture;

public class AsyncTaskChain {
    public static void main(String[] args) {
        CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "10");

        CompletableFuture<Integer> task2 = task1.thenApplyAsync(s -> {
            try {
                return Integer.parseInt(s);
            } catch (NumberFormatException e) {
                return -1;
            }
        });

        CompletableFuture<Integer> task3 = task2.thenApplyAsync(i -> {
            if (i != -1) {
                return i * i;
            }
            return -1;
        });

        task3.thenAccept(System.out::println).join();
    }
}

每一步链式调用方法的意义

  1. supplyAsync:
    • 用于异步执行一个有返回值的任务。在task1中,CompletableFuture.supplyAsync(() -> "10")创建了一个异步任务,该任务返回字符串"10"。这里使用supplyAsync是因为任务有返回值,且希望异步执行以提高效率。
  2. thenApplyAsync:
    • task2中,task1.thenApplyAsync(s -> { ... })接收task1的返回值(字符串)作为参数s,并异步地将其转换为整数。这里使用thenApplyAsync而不是thenApply是为了在新的线程中执行转换操作,避免阻塞主线程。在这个lambda表达式中,尝试将字符串解析为整数,如果解析失败,捕获NumberFormatException并返回默认值-1
    • task3中,task2.thenApplyAsync(i -> { ... })接收task2的返回值(整数)作为参数i,并异步地将其平方。同样使用thenApplyAsync以异步执行平方操作。如果i不等于-1(即解析成功),则返回平方值;否则返回-1
  3. thenAccept:
    • task3.thenAccept(System.out::println)接收task3的返回值,并对其进行消费。这里将task3的返回值打印输出。thenAccept适用于只需要处理返回值而不需要返回新结果的情况。

异常处理机制

  1. 解析异常处理:
    • task2thenApplyAsync中,通过try - catch块捕获NumberFormatException异常,当字符串解析为整数失败时,返回默认值-1。这样就避免了异常向上传播,保证了后续任务task3能正常接收一个有效值(即使是默认值)。
  2. 平方异常处理:
    • task3thenApplyAsync中,通过判断i是否等于-1来处理可能在解析阶段产生的异常影响。如果i-1,直接返回-1,而不进行平方操作,从而避免因异常解析值导致的运行时错误。同时,如果在平方过程中出现其他异常(如Integer溢出,这里未详细处理,但理论上可以在try - catch块中捕获处理),也可以类似地进行异常捕获并返回默认值。

综上所述,通过CompletableFuture的链式调用和异常处理机制,实现了一系列异步任务的顺序执行,并在遇到异常时返回默认值。