CompletableFuture学习手册

本文深入探讨了Java中的异步计算,重点关注CompletableFuture类。通过示例介绍了如何使用CompletableFuture作为简单的Future、封装计算逻辑、处理异步计算结果、合并Future、处理错误以及并行运行多个Future。特别强调了thenApply()和thenCompose()的区别,以及如何处理异步方法中的错误。
摘要由CSDN通过智能技术生成

Java中的异步计算

异步计算很难推理。通常,我们希望将任何计算视为一系列步骤,但在异步计算的情况下,表示为回调的操作往往分散在代码中或彼此深度嵌套。当我们需要处理在其中一个步骤中可能发生的错误时,情况会变得更糟。
Future接口是在Java 5中添加的,作为异步计算的结果,但它没有任何方法来组合这些计算或处理可能的错误。
Java 8 引入了CompletableFuture。除了Future接口之外,它还实现了CompletionStage接口。此接口定义了我们可以与其他步骤组合的异步计算步骤的协定。
CompletableFuture同时是一个构建块和一个框架,有大约50种不同的方法来组合,组合和执行异步计算步骤以及处理错误
如此庞大的API可能会让人不知所措,但这些大多落在几个清晰而独特的用例中。

使用Completable作为一个简单的Future

首先,CompletableFuture 类实现了 Future 接口,因此我们可以将其用作 Future 实现,但具有额外的完成逻辑
例如,我们可以创建一个无参构造函数的此类实例来表示将来的某个结果,将其分发给使用者,并在将来的某个时间使用完整方法完成它。使用者可以使用 get 方法阻止当前线程,直到提供此结果。
在下面的示例中,我们有一个创建CompletableFuture实例的方法,然后在另一个线程中分离出一些计算并立即返回Future
计算完成后,该方法通过给complete方法提供结果完成Future

public Future<String> calculateAsync() throws InterruptedException {
   
        CompletableFuture<String> completableFuture = new CompletableFuture<>();

        Executors.newCachedThreadPool().submit(() -> {
   
            Thread.sleep(500);
            completableFuture.complete("hello");
            return null;
        });
        
        return completableFuture;
    }

为了分拆计算,我们使用Executor API。这种创建和完成 CompletableFuture 的方法可与任何并发机制或 API(包括原始线程)一起使用。
请注意,calculateAsync 方法返回一个 Future 实例
我们只需调用该方法,接收 Future 实例,并在准备好阻止结果时调用get方法。
还要观察 get 方法会引发一些已检查的异常,即 ExecutionException(封装计算期间发生的异常)和 InterruptedException(表示执行方法的线程被中断的异常):

        Future<String> completableFuture = calculateAsync();

        //……
        
        String result = completableFuture.get();
        System.out.println("hello".equals(result));

如果我们已经知道计算的结果,我们可以使用静态completedFuture 方法,并带有表示此计算结果的参数。因此,Futureget 方法永远不会阻塞,而是立即返回此结果:

        CompletableFuture<String> completableFuture = CompletableFuture.completedFuture("hello");
        
        //……

        String result = completableFuture.get();
        System.out.println("hello".equals(result));

作为替代方案,我们可能希望取消Future的执行。

具有封装计算逻辑的CompletableFuture

上面的代码允许我们选择任何并发执行的机制,但是如果我们想跳过这个样板并简单地异步执行一些代码呢?
静态方法runAsyncsupplyAsync允许我们相应地从RunnableSupplier 函数类型中创建CompletableFuture实例。
RunnableSupplier 都是函数接口,由于采用了Java8新特性,它们允许将其实例作为 lambda 表达式传递。
Runnable 接口与线程中使用的旧接口相同,它不允许返回值。
Supplier 接口是一个泛型函数接口,具有单个方法,该方法没有参数,并返回参数化类型的值。
这允许我们提供Supplier的实例作为 lambda 表达式,用于执行计算并返回结果。它就像这样简单:

        // 返回一个新的 CompletableFuture,它由在ForkJoinPool.commonPool()中运行的任务异步完成,其值通过调用给定的Supplier获得。
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值