使用CompletableFuture进行异步编程

CompletableFuture是Java 8中引入的一个异步编程工具,它实现了Future和CompletionStage接口,可以用于处理异步任务。CompletableFuture提供了丰富的方法,可以方便地组合多个异步任务,实现复杂的异步逻辑。本文将介绍CompletableFuture的使用。

1. 创建CompletableFuture

要创建一个CompletableFuture,可以使用以下静态方法:

supplyAsync(Supplier<U> supplier): 使用一个供应者函数(Supplier)创建一个异步任务。

runAsync(Runnable runnable): 使用一个Runnable对象创建一个异步任务。

completedFuture(U value): 创建一个已经完成的CompletableFuture。

exceptionally(Function<Throwable, ? extends T> fn): 当异步任务发生异常时,使用一个异常函数处理异常。

 

2. 组合多个异步任务

CompletableFuture提供了很多方法,可以方便地组合多个异步任务。以下是一些常用的组合方法:

thenApply(Function<? super T,? extends U> fn): 对异步任务的结果应用一个函数,并返回一个新的CompletableFuture。

thenAccept(Consumer<? super T> action): 对异步任务的结果执行一个操作,并返回一个新的CompletableFuture。

thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn): 当两个异步任务都完成时,使用一个函数组合它们的结果,并返回一个新的CompletableFuture。

thenCompose(Function<? super T, ? extends CompletionStage<U>> fn): 当异步任务完成时,将其结果应用于另一个异步任务,并返回一个新的CompletableFuture。

allOf(CompletableFuture<?>... cfs): 等待所有给定的CompletableFuture都完成,然后返回一个新的CompletableFuture。

anyOf(CompletableFuture<?>... cfs): 只要给定的任意一个CompletableFuture完成,就返回一个新的CompletableFuture。

 

3. 获取异步任务的结果

可以使用以下方法获取异步任务的结果:

get(): 阻塞当前线程,等待异步任务完成,并返回结果。注意:这个方法会抛出InterruptedException和ExecutionException异常,需注意异常处理。

get(long timeout, TimeUnit unit): 与get()方法一样,区别是增加了等待异步任务完成的超时时间,并且会抛出TimeoutException异常。

join(): 阻塞当前线程,等待异步任务完成,并返回结果。与get()方法类似,但不会抛出异常。

isDone(): 判断异步任务是否已完成。如果已完成,返回true;否则返回false。

isCompletedExceptionally(): 判断异步任务是否因异常而完成。如果因异常而完成,返回true;否则返回false。

exceptionally(Function<Throwable, ? extends T> fn): 当异步任务发生异常时,使用一个异常函数处理异常,并返回一个新的CompletableFuture。

 

4. 示例代码

下面是一个简单的示例,演示了如何使用CompletableFuture组合多个异步任务:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CompletableFutureDemo {
    private static final Logger LOGGER = LoggerFactory.getLogger(CompletableFutureDemo.class);

    public static void main(String[] args) throws Exception {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            sleep(1000);
            return "Hello";
        });
        future1.thenApply(s -> s + " World").thenAccept(message -> LOGGER.info(message));

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            sleep(1000);
            return "Hello Timeout";
        });

        CompletableFuture<Object> future3 = CompletableFuture.supplyAsync(() -> {
            sleep(50);
            throw new RuntimeException();
        }).exceptionally(ex -> {
            // 处理异常并返回默认值或执行其他操作
            LOGGER.info("future3" + ex.getMessage());
            return "默认值";
        });

        LOGGER.info("主线程继续执行");

        try {
            // 模拟获取结果超时
            String result2 = future2.get(500, TimeUnit.MILLISECONDS);
            LOGGER.info(result2);
        } catch (TimeoutException e) {
            LOGGER.info("future2超时");
        }

        // future3使用了exceptionally(),future3.isCompletedExceptionally()不会为true
        String result3 = (String) future3.get();
        LOGGER.info(result3 + " " + future3.isCompletedExceptionally());

        CompletableFuture.allOf(future1, future2, future3).join(); // 等待所有任务完成
        LOGGER.info("主线程结束");
    }

    private static void sleep(long millis) {
        try {
            TimeUnit.MILLISECONDS.sleep(millis);
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }
    }
}

程序输出如下:

18:43:50.408 [main] INFO  CompletableFutureDemo - 主线程继续执行
18:43:50.460 [ForkJoinPool.commonPool-worker-3] INFO  CompletableFutureDemo - future3java.lang.RuntimeException
18:43:50.916 [main] INFO  CompletableFutureDemo - future2超时
18:43:50.916 [main] INFO  CompletableFutureDemo - 默认值 false
18:43:51.404 [ForkJoinPool.commonPool-worker-1] INFO  CompletableFutureDemo - Hello World
18:43:51.404 [main] INFO  CompletableFutureDemo - 主线程结束

从上述输出可以看出,多个CompletableFuture与主线程并行执行,并且不会相互影响。这意味着每个CompletableFuture都可以独立地执行其任务,而不需要等待其他任务完成。此外,由于CompletableFuture是异步的,它们不会阻塞主线程的执行,这种并行执行的方式可以提高应用的性能和效率。

 

总结

CompletableFuture是一个强大的异步编程工具,可以方便地组合多个异步任务,实现复杂的异步逻辑。通过使用CompletableFuture,我们可以实现高效的并发编程,并充分利用多核处理器的能力。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

创意程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值