CompletableFuture

CompletableFuture的用法

CompletableFuture 是 Java 8 引入的一个类,用于处理异步编程。它提供了丰富的 API 来处理异步任务的执行、组合和处理结果。以下是 CompletableFuture 的一些常见用法:

1. 创建 CompletableFuture

  • 直接创建一个完成的 CompletableFuture
CompletableFuture<String> completedFuture = CompletableFuture.completedFuture("Hello");
  • 通过异步任务创建 CompletableFuture
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    // 异步任务
    System.out.println("Running in a separate thread");
});

2. 组合多个 CompletableFuture

  • 使用 thenApply 处理结果
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
    .thenApply(result -> result + " World");
  • 使用 thenAccept 处理结果,无返回值
CompletableFuture.supplyAsync(() -> "Hello")
    .thenAccept(result -> System.out.println(result + " World"));
  • 使用 thenCompose 链接多个异步任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
    .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " World"));
  • 使用 thenCombine 合并两个 CompletableFuture 的结果
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");

CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + " " + result2);

3. 处理异常

  • 使用 exceptionally 处理异常
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (true) {
        throw new RuntimeException("Exception occurred");
    }
    return "Hello";
}).exceptionally(ex -> "Error: " + ex.getMessage());
  • 使用 handle 处理结果和异常
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (true) {
        throw new RuntimeException("Exception occurred");
    }
    return "Hello";
}).handle((result, ex) -> {
    if (ex != null) {
        return "Error: " + ex.getMessage();
    }
    return result;
});

4. 等待所有任务完成

  • 使用 allOf 等待所有 CompletableFuture 完成
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");

CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2);

allOf.thenRun(() -> {
    try {
        System.out.println(future1.get() + " " + future2.get());
    } catch (Exception e) {
        e.printStackTrace();
    }
});

5. 等待任意一个任务完成

  • 使用 anyOf 等待任意一个 CompletableFuture 完成
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");

CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2);

anyOf.thenAccept(result -> System.out.println(result));

6. 超时处理

  • 使用 orTimeout 设置超时
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello";
}).orTimeout(1, TimeUnit.SECONDS).exceptionally(ex -> "Timeout: " + ex.getMessage());
  • 使用 completeOnTimeout 设置超时并提供默认值
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello";
}).completeOnTimeout("Default Value", 1, TimeUnit.SECONDS);

总结

CompletableFuture 提供了丰富的 API 来处理异步任务,包括任务的创建、组合、异常处理、超时处理等。通过这些 API,你可以轻松地实现复杂的异步编程逻辑。

如何获取异步执行的结果

在 Java 中,CompletableFuture 提供了多种方式来获取异步执行的结果。以下是几种常见的方法:

  1. get() 方法
    这是最常用的方法之一。它会阻塞当前线程,直到 CompletableFuture 完成并返回结果。

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        // 异步任务
        return "Hello, World!";
    });
    
    try {
        String result = future.get();
        System.out.println(result); // 输出: Hello, World!
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
    
  2. join() 方法
    类似于 get() 方法,但它会抛出未经检查的异常(CompletionException),而不是受检异常。

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        // 异步任务
        return "Hello, World!";
    });
    
    String result = future.join();
    System.out.println(result); // 输出: Hello, World!
    
  3. thenApply() 方法
    该方法允许在 CompletableFuture 完成后对结果进行处理,并返回一个新的 CompletableFuture

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        // 异步任务
        return "Hello, World!";
    });
    
    CompletableFuture<String> processedFuture = future.thenApply(result -> {
        return result + " Processed!";
    });
    
    String processedResult = processedFuture.join();
    System.out.println(processedResult); // 输出: Hello, World! Processed!
    
  4. thenAccept() 方法
    该方法允许在 CompletableFuture 完成后对结果进行消费,但不返回新的 CompletableFuture

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        // 异步任务
        return "Hello, World!";
    });
    
    future.thenAccept(result -> {
        System.out.println(result); // 输出: Hello, World!
    });
    
  5. whenComplete() 方法
    该方法允许在 CompletableFuture 完成后执行一个回调,无论是正常完成还是异常完成。

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        // 异步任务
        return "Hello, World!";
    });
    
    future.whenComplete((result, exception) -> {
        if (exception == null) {
            System.out.println(result); // 输出: Hello, World!
        } else {
            exception.printStackTrace();
        }
    });
    
  6. handle() 方法
    该方法允许在 CompletableFuture 完成后对结果或异常进行处理,并返回一个新的 CompletableFuture

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        // 异步任务
        return "Hello, World!";
    });
    
    CompletableFuture<String> handledFuture = future.handle((result, exception) -> {
        if (exception == null) {
            return result + " Handled!";
        } else {
            return "Exception occurred!";
        }
    });
    
    String handledResult = handledFuture.join();
    System.out.println(handledResult); // 输出: Hello, World! Handled!
    

void类型,调用get方法后

如果 CompletableFuture 的类型是 Void,你仍然可以使用 get() 方法来等待异步任务的完成。尽管 get() 方法会返回 null,但它会确保异步任务已经完成。

以下是一个示例:

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    // 异步任务
    System.out.println("Task is running");
});

try {
    // 调用 get() 方法等待任务完成
    future.get();
    System.out.println("Task completed");
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

在这个示例中,CompletableFuture.runAsync() 方法创建了一个异步任务,该任务不返回任何结果(即 Void 类型)。调用 get() 方法会阻塞当前线程,直到异步任务完成。

其他获取 Void 类型 CompletableFuture 结果的方法

  1. join() 方法
    类似于 get() 方法,但它会抛出未经检查的异常(CompletionException),而不是受检异常。

    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        // 异步任务
        System.out.println("Task is running");
    });
    
    // 调用 join() 方法等待任务完成
    future.join();
    System.out.println("Task completed");
    
  2. thenRun() 方法
    该方法允许在 CompletableFuture 完成后执行一个回调,但不返回新的 CompletableFuture

    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        // 异步任务
        System.out.println("Task is running");
    });
    
    future.thenRun(() -> {
        System.out.println("Task completed");
    });
    
  3. whenComplete() 方法
    该方法允许在 CompletableFuture 完成后执行一个回调,无论是正常完成还是异常完成。

    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        // 异步任务
        System.out.println("Task is running");
    });
    
    future.whenComplete((result, exception) -> {
        if (exception == null) {
            System.out.println("Task completed");
        } else {
            exception.printStackTrace();
        }
    });
    
  4. handle() 方法
    该方法允许在 CompletableFuture 完成后对结果或异常进行处理,并返回一个新的 CompletableFuture

    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        // 异步任务
        System.out.println("Task is running");
    });
    
    CompletableFuture<Void> handledFuture = future.handle((result, exception) -> {
        if (exception == null) {
            System.out.println("Task completed");
        } else {
            System.out.println("Exception occurred");
        }
        return null;
    });
    
    // 调用 join() 方法等待处理完成
    handledFuture.join();
    

如果不需要等待返回值

如果不需要等待 CompletableFuture 的返回值,只需要启动异步任务并继续执行后续代码,可以使用以下几种方法:

  1. runAsync() 方法
    该方法用于启动一个不返回结果的异步任务。

    CompletableFuture.runAsync(() -> {
        // 异步任务
        System.out.println("Task is running");
    });
    
    // 后续代码
    System.out.println("Task has been started");
    
  2. supplyAsync() 方法
    该方法用于启动一个返回结果的异步任务,但你可以忽略返回值。

    CompletableFuture.supplyAsync(() -> {
        // 异步任务
        System.out.println("Task is running");
        return "Result";
    });
    
    // 后续代码
    System.out.println("Task has been started");
    
  3. 链式调用
    如果你需要在异步任务完成后执行一些操作,但不需要等待结果,可以使用 thenRun()thenAccept() 方法。

    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        // 异步任务
        System.out.println("Task is running");
    });
    
    future.thenRun(() -> {
        // 异步任务完成后的操作
        System.out.println("Task completed");
    });
    
    // 后续代码
    System.out.println("Task has been started");
    
  4. 组合多个异步任务
    如果你有多个异步任务,并且不需要等待它们的结果,可以使用 allOf() 方法。

    CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
        // 异步任务1
        System.out.println("Task 1 is running");
    });
    
    CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
        // 异步任务2
        System.out.println("Task 2 is running");
    });
    
    CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
    
    allFutures.thenRun(() -> {
        // 所有异步任务完成后的操作
        System.out.println("All tasks completed");
    });
    
    // 后续代码
    System.out.println("Tasks have been started");
    

总结:如果你不需要等待 CompletableFuture 的返回值,只需要启动异步任务并继续执行后续代码,可以直接调用 runAsync()supplyAsync() 方法,并在需要时使用链式调用来处理任务完成后的操作。这样可以确保异步任务在后台执行,而主线程继续执行后续代码。

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你这个代码我看不懂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值