Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >阅读 Flink 源码前必会的知识 - Java 8 异步编程 CompletableFuture 全解析

阅读 Flink 源码前必会的知识 - Java 8 异步编程 CompletableFuture 全解析

作者头像
kk大数据
发布于 2021-03-13 14:24:01
发布于 2021-03-13 14:24:01
1.1K00
代码可运行
举报
文章被收录于专栏:kk大数据kk大数据
运行总次数:0
代码可运行

本文大纲速看

一、异步编程

通常来说,程序都是顺序执行,同一时刻只会发生一件事情。如果一个函数依赖于另一个函数的结果,它只能等待那个函数结束才能继续执行,从用户角度来说,整个程序才算执行完毕。

但现在的计算机普遍拥有多核 CPU,在那里干等着毫无意义,完全可以在另一个处理器内核上干其他工作,耗时长的任务结束之后会主动通知你。这就是异步编程的出发点:充分使用多核 CPU 的优势,最大程度提高程序性能。

一句话来说:所谓异步编程,就是实现一个无需等待被调用函数的返回值而让操作继续运行的方法。

二、抛出一个问题:如何实现烧水泡茶的程序

最后我们会使用传统方式和 Java8 异步编程方式分别实现,来对比一下实现复杂度。

三、Java5 的 Future 实现的异步编程

Future 是 Java 5 添加的类,用来描述一个异步计算的结果。你可以使用 isDone() 方法检查计算是否完成,或者使用 get() 方法阻塞住调用线程,直到计算完成返回结果,也可以使用 cancel() 方法停止任务的执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService es = Executors.newFixedThreadPool(5);
        Future<Integer> f = es.submit(() -> 100);
        System.out.println(f.get());
        es.shutdown();
    }

虽然 Future 提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们异步编程的初衷相违背,轮询的方式又会耗费无谓的 CPU 资源,而且也不能及时的获取结果。

当然,很多其他的语言采用回调的方式来实现异步编程,比如 Node.js;Java 的一些框架,比如 Netty,Google Guava 也扩展了 Future 接口,提供了很多回调的机制,封装了工具类,辅助异步编程开发。

Java 作为老牌编程语言,自然也不会落伍。在 Java 8 中,新增了一个包含 50 多个方法的类:CompletableFuture,提供了非常强大的 Future 扩展功能,可以帮助我们简化异步编程的复杂性,提供函数式编程的能力。

四、CompletableFuture 类功能概览

如下图是 CompletableFuture 实现的接口:

它实现了 Future 接口,拥有 Future 所有的特性,比如可以使用 get() 方法获取返回值等;还实现了 CompletionStage 接口,这个接口有超过 40 个方法,功能太丰富了,它主要是为了编排任务的工作流。

我们可以把工作流和工作流之间的关系分类为三种:串行关系,并行关系,汇聚关系。

  • 串行关系

提供了如下的 api 来实现(先大致浏览一遍):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CompletionStage<R> thenApply(fn);
CompletionStage<R> thenApplyAsync(fn);
CompletionStage<Void> thenAccept(consumer);
CompletionStage<Void> thenAcceptAsync(consumer);
CompletionStage<Void> thenRun(action);
CompletionStage<Void> thenRunAsync(action);
CompletionStage<R> thenCompose(fn);
CompletionStage<R> thenComposeAsync(fn);
  • 并行关系

多线程异步执行就是并行关系

  • 汇聚关系

汇聚关系,又分为 AND 汇聚关系和 OR 汇聚关系:

AND 汇聚关系,就是所有依赖的任务都完成之后再执行;OR 汇聚关系,就是依赖的任务中有一个执行完成,就开始执行。

AND 汇聚关系由这些接口表达:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CompletionStage<R> thenCombine(other, fn);
CompletionStage<R> thenCombineAsync(other, fn);
CompletionStage<Void> thenAcceptBoth(other, consumer);
CompletionStage<Void> thenAcceptBothAsync(other, consumer);
CompletionStage<Void> runAfterBoth(other, action);
CompletionStage<Void> runAfterBothAsync(other, action);

OR 汇聚关系由这些接口来表达:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CompletionStage applyToEither(other, fn);
CompletionStage applyToEitherAsync(other, fn);
CompletionStage acceptEither(other, consumer);
CompletionStage acceptEitherAsync(other, consumer);
CompletionStage runAfterEither(other, action);
CompletionStage runAfterEitherAsync(other, action);

五、CompletableFuture 接口精讲

1、提交执行的静态方法

方法名

描述

runAsync(Runnable runnable)

执行异步代码,使用 ForkJoinPool.commonPool() 作为它的线程池

runAsync(Runnable runnable, Executor executor)

执行异步代码,使用指定的线程池

supplyAsync(Supplier<U> supplier)

异步执行代码,有返回值,使用 ForkJoinPool.commonPool() 作为它的线程池

supplyAsync(Supplier<U> supplier, Executor executor)

异步执行代码,有返回值,使用指定的线程池执行

上述四个方法,都是提交任务的,runAsync 方法需要传入一个实现了 Runnable 接口的方法,supplyAsync 需要传入一个实现了 Supplier 接口的方法,实现 get 方法,返回一个值。

(1)run 和 supply 的区别

run 就是执行一个方法,没有返回值,supply 执行一个方法,有返回值。

(2)一个参数和两个参数的区别

第二个参数是线程池,如果没有传,则使用自带的 ForkJoinPool.commonPool() 作为线程池,这个线程池默认创建的线程数是 CPU 的核数(也可以通过 JVM option:-Djava.util.concurrent.ForkJoinPool.common.parallelism 来设置 ForkJoinPool 线程池的线程数)

2、串行关系 api

这些 api 之间主要是能否获得前一个任务的返回值与自己是否有返回值的区别。

api

是否可获得前一个任务的返回值

是否有返回值

thenApply

thenAccept

thenRun

不能

thenCompose

(1) thenApply 和 thenApplyAsync 使用

thenApply 和 thenApplyAsync 把两个并行的任务串行化,另一个任务在获得上一个任务的返回值之后,做一些加工和转换。它也是有返回值的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class BasicFuture4 {

    @Data
    @AllArgsConstructor
    @ToString
    static class Student {
        private String name;
    }
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Student> future = CompletableFuture.supplyAsync(() -> "Jack")
                .thenApply(s -> s + " Smith")
                .thenApply(String::toUpperCase)
                .thenApplyAsync(Student::new);
        System.out.println(future.get());
    }

}

结果可以看到,输入是一个字符串,拼接了一个字符串,转换成大写,new 了一个 Student 对象返回。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
BasicFuture4.Student(name=JACK SMITH)

和 thenApply 一起的还有 thenAccept 和 thenRun,thenAccept 能获得到前一个任务的返回值,但是自身没有返回值;thenRun 不能获得前一个任务的返回值,自身也没有返回值。

(2)thenApply 和 thenApplyAsync 的区别

这两个方法的区别,在于谁去执行任务。如果使用 thenApplyAsync,那么执行的线程是从 ForkJoinPool.commonPool() 或者自己定义的线程池中取线程去执行。如果使用 thenApply,又分两种情况,如果 supplyAsync 方法执行速度特别快,那么 thenApply 任务就使用主线程执行,如果 supplyAsync 执行速度特别慢,就是和 supplyAsync 执行线程一样。

可以使用下面的例子演示一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.dsj361.future;

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

/**
 * @Author wangkai
 */
public class BasicFuture8 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("----------supplyAsync 执行很快");
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            return "1";
        }).thenApply(s -> {
            System.out.println(Thread.currentThread().getName());
            return "2";
        });
        System.out.println(future1.get());

        System.out.println("----------supplyAsync 执行很慢");
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread().getName());
            return "1";
        }).thenApply(s -> {
            System.out.println(Thread.currentThread().getName());
            return "2";
        });
        System.out.println(future2.get());
    }
}

执行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
----------supplyAsync 执行很快
ForkJoinPool.commonPool-worker-1
main
2
----------supplyAsync 执行很慢
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
2
(3)thenCompose 的使用

假设有两个异步任务,第二个任务想要获取第一个任务的返回值,并且做运算,我们可以用 thenCompose。此时使用 thenApply 也可以实现,看一段代码发现他们的区别:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class BasicFuture9 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = getLastOne().thenCompose(BasicFuture9::getLastTwo);
        System.out.println(future.get());

        CompletableFuture<CompletableFuture<String>> future2 = getLastOne().thenApply(s -> getLastTwo(s));
        System.out.println(future2.get().get());
    }

    public static CompletableFuture<String> getLastOne(){
        return CompletableFuture.supplyAsync(()-> "topOne");
    }

    public static CompletableFuture<String> getLastTwo(String s){
        return CompletableFuture.supplyAsync(()-> s + "  topTwo");
    }
}

可以看到使用 thenApply 的时候,需要使用两个 get() 方法才能获取到最终的返回值,使用 thenCompose 只要一个即可。

3、And 汇聚关系 Api
(1)thenCombine 的使用

加入我们要计算两个异步方法返回值的和,就必须要等到两个异步任务都计算完才能求和,此时可以用 thenCombine 来完成。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) throws ExecutionException, InterruptedException {
    CompletableFuture<Integer> thenComposeOne = CompletableFuture.supplyAsync(() -> 192);
    CompletableFuture<Integer> thenComposeTwo = CompletableFuture.supplyAsync(() -> 196);
    CompletableFuture<Integer> thenComposeCount = thenComposeOne
        .thenCombine(thenComposeTwo, (s, y) -> s + y);

    thenComposeOne.thenAcceptBoth(thenComposeTwo,(s,y)-> System.out.println("thenAcceptBoth"));
    thenComposeOne.runAfterBoth(thenComposeTwo, () -> System.out.println("runAfterBoth"));

    System.out.println(thenComposeCount.get());
}

可以看到 thenCombine 第二个参数是一个 Function 函数,前面两个异步任务都完成之后,使用这个函数来完成一些运算。

(2)thenAcceptBoth

接收前面两个异步任务的结果,执行一个回调函数,但是这个回调函数没有返回值。

(3)runAfterBoth

接收前面两个异步任务的结果,但是回调函数,不接收参数,也不返回值。

4、Or 汇聚关系 Api
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class BasicFuture11 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> thenComposeOne = CompletableFuture.supplyAsync(() -> 192);
        CompletableFuture<Integer> thenComposeTwo = CompletableFuture.supplyAsync(() -> 196);
        CompletableFuture<Integer> thenComposeCount = thenComposeOne
                .applyToEither(thenComposeTwo, s -> s + 1);

        thenComposeOne.acceptEither(thenComposeTwo,s -> {});
        
        thenComposeOne.runAfterEither(thenComposeTwo,()->{});

        System.out.println(thenComposeCount.get());
    }
}
(1)applyToEither

任何一个执行完就执行回调方法,回调方法接收一个参数,有返回值

(2)acceptEither

任何一个执行完就执行回调方法,回调方法接收一个参数,无返回值

(3)runAfterEither

任何一个执行完就执行回调方法,回调方法不接收参数,也无返回值

5、处理异常

上面我们讲了如何把几个异步任务编排起来,执行一些串行或者汇聚操作。还有一个重要的地方,就是异常的处理。

先看下面的例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) throws ExecutionException, InterruptedException {
    CompletableFuture.supplyAsync(() -> {
        System.out.println("execute one ");
        return 100;
    })
        .thenApply(s -> 10 / 0)
        .thenRun(() -> System.out.println("thenRun"))
        .thenAccept(s -> System.out.println("thenAccept"));

    CompletableFuture.runAsync(() -> System.out.println("other"));
}

结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
execute one 
other

可以发现,只要链条上有一个任务发生了异常,这个链条下面的任务都不再执行了。

但是 main 方法上的接下来的代码还是会执行的。

所以这个时候,需要合理的去处理异常来完成一些收尾的工作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class BasicFuture12 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture.supplyAsync(() -> {
            System.out.println("execute one ");
            return 100;
        })
                .thenApply(s -> 10 / 0)
                .thenRun(() -> System.out.println("thenRun"))
                .thenAccept(s -> System.out.println("thenAccept"))
                .exceptionally(s -> {
                    System.out.println("异常处理");
                    return null;
                });

        CompletableFuture.runAsync(() -> System.out.println("other"));
    }
}

可以使用 exceptionally 来处理异常。

使用 handle() 方法也可以处理异常。但是 handle() 方法的不同之处在于,即使没有发生异常,也会执行。

六、烧水泡茶程序的实现

1、使用 Thread 多线程和 CountDownLatch 来实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MakeTee {

    private static CountDownLatch countDownLatch = new CountDownLatch(2);

    static class HeatUpWater implements Runnable {

        private CountDownLatch countDownLatch;

        public HeatUpWater(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }
        @Override
        public void run() {
            try {
                System.out.println("洗水壶");
                Thread.sleep(1000);
                System.out.println("烧开水");
                Thread.sleep(5000);
                countDownLatch.countDown();
            } catch (InterruptedException e) {
            }

        }
    }

    static class PrepareTee implements Runnable {
        private CountDownLatch countDownLatch;

        public PrepareTee(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            try {
                System.out.println("洗茶壶");
                Thread.sleep(1000);
                System.out.println("洗茶杯");
                Thread.sleep(1000);
                System.out.println("拿茶叶");
                Thread.sleep(1000);
                countDownLatch.countDown();
            } catch (InterruptedException e) {
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        new Thread(new HeatUpWater(countDownLatch) ).start();
        new Thread(new PrepareTee(countDownLatch)).start();
        countDownLatch.await();
        System.out.println("准备就绪,开始泡茶");
    }
}

这里我们使用两个线程,分别执行烧水和泡茶的程序,使用 CountDownLatch 来协调两个线程的进度,等到他们都执行完成之后,再执行泡茶的动作。

可以看到这种方法,多了很多不必要的代码,new Thread,人工维护 CountDownLatch 的进度。

2、使用 CompletableFuture 来实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MakeTeeFuture {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            try {
                System.out.println("洗水壶");
                Thread.sleep(1000);
                System.out.println("烧开水");
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            try {
                System.out.println("洗茶壶");
                Thread.sleep(1000);
                System.out.println("洗茶杯");
                Thread.sleep(1000);
                System.out.println("拿茶叶");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        CompletableFuture<Void> finish = future1.runAfterBoth(future2, () -> {
            System.out.println("准备完毕,开始泡茶");
        });
        System.out.println(finish.get());
    }
}

这个程序极度简单,无需手工维护线程,给任务分配线程的工作也不需要关注。

同时语义也更加清晰,future1.runAfterBoth(future2,......) 能够清晰的表述“任务 3 要等到任务 1 和任务 2 都完成之后才能继续开始”

然后代码更加简练并且专注于业务逻辑,几乎所有的代码都是业务逻辑相关的。

七、总结

本文介绍了异步编程的概念,以及 Java8 的 CompletableFuture 是如何优雅的处理多个异步任务之间的协调工作的。CompletableFuture 能够极大简化我们对于异步任务编排的工作,Flink 在提交任务时,也是使用这种异步任务的方式,去编排提交时和提交后对于任务状态处理的一些工作的。

相信读了本篇文章,会对于你日后的工作以及阅读 Flink 源码由很大的帮助的!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 KK架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JUC并发—13.Future模式和异步编程简介
Callable接口需要与Future和ExecutorService结合使用:通过ExecutorService的submit()方法提交一个实现Callable接口的任务,然后ExecutorService的submit()方法会返回一个实现Future接口的对象,接着调用Future接口的get()方法就可以获取异步任务的结果。
东阳马生架构
2025/05/06
620
深度解析CompletableFuture:Java 异步世界的奇迹
上文我们可知:CompletableFuture 是 Java 8 引入用于支持异步编程和非阻塞操作的类。对于没有使用过CompletableFuture通过它这么长的名字就感觉到一头雾水,那么现在我们来一起解读一下它的名字。
关忆北.
2023/11/13
6120
深度解析CompletableFuture:Java 异步世界的奇迹
异步编程利器:CompletableFuture详解
最近刚好使用CompeletableFuture优化了项目中的代码,所以跟大家一起学习CompletableFuture。
捡田螺的小男孩
2021/06/15
6.8K0
异步编程利器:CompletableFuture详解
理解Java8里面CompletableFuture异步编程
其中第三个特性,就是今天我们想要聊的话题,正是因为CompletableFuture的出现,才使得使用Java进行异步编程提供了可能。
我是攻城师
2018/11/23
16.7K0
CompletableFuture 使用详解
没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。以下所有的方法都类同。
java404
2018/10/10
4.1K1
CompletableFuture详解
因为CompletableFuture实现了Future接口所以先看一下Future
用户10136162
2022/11/15
1K0
CompletableFuture详解
【并发编程】异步编程CompletableFuture实战
在JDK8之前,我们使用的Java多线程变成,主要是 Thread+Runnable 来完成,但是这种方式有个弊端就是没有返回值。如果想要返回值怎么办呢,大多数人就会想到 Callable + Thread 的方式来获取到返回值。
互联网小阿祥
2023/05/28
1.1K0
【并发编程】异步编程CompletableFuture实战
CompletableFuture介绍
一个Future类是显示的完成,而且能被用作一个完成等级,通过它的完成触发支持的依赖函数和行为。当两个或多个线程要执行完成或取消操作时,只有一个能够成功。
HLee
2021/07/12
2.1K0
CompletableFuture介绍
并发编程系列-CompletableFuture
利用多线程来提升性能,实质上是将顺序执行的操作转化为并行执行。仔细观察后,你还会发现在顺序转并行的过程中,一定会牵扯到异步化。举个例子,现在下面这段示例代码是按顺序执行的,为了优化性能,我们需要将其改为并行执行。那具体的实施方法是什么呢?
架构狂人
2023/08/16
1990
并发编程系列-CompletableFuture
CompletableFuture学习
前面我们已经知道CompletionService是可以解决Future带来的阻塞问题的,同时我们除了前面我们看到的take方法之外,还可以使用poll方法,这样可以使你的程序免受阻塞之苦。因为poll方法也是无阻塞性的。同时在kafka的源码中,我们如果使用消费者的话,可以看到会使用一个基于future的poll方法。同时我们可以在dubbo的新版本2.7中,可以看到其异步编程采用的就是我们要介绍的CompletableFuture。因此,我们有必要了解CompletableFuture,同时其也是真正意义上的异步编程的实现。
路行的亚洲
2020/07/16
1.1K0
异步神器CompletableFuture
上个礼拜我们线上有个接口比较慢,这个接口在刚开始响应时间是正常的。但随着数据量的增多,响应时间变慢了。
Java识堂
2020/09/14
1.2K0
基础篇:异步编程不会?我教你啊!CompeletableFuture
以前需要异步执行一个任务时,一般是用Thread或者线程池Executor去创建。如果需要返回值,则是调用Executor.submit获取Future。但是多个线程存在依赖组合,我们又能怎么办?可使用同步组件CountDownLatch、CyclicBarrier等;其实有简单的方法,就是用CompletableFuture
潜行前行
2020/12/11
7890
基础篇:异步编程不会?我教你啊!CompeletableFuture
CompletableFuture 异步多线程,那叫一个优雅
虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,我们必须使用Future.get()的方式阻塞调用线程,或者使用轮询方式判断 Future.isDone 任务是否结束,再获取结果。
程序员大彬
2023/03/01
1.6K0
CompletableFuture 异步多线程,那叫一个优雅
一网打尽:异步神器 CompletableFuture 万字详解!
CompletableFuture是jdk8的新特性。CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步会点、流式处理、多个Future组合处理的能力,使Java在处理多任务的协同工作时更加顺畅便利。
搜云库技术团队
2023/09/18
2.7K0
一网打尽:异步神器 CompletableFuture 万字详解!
【小家java】Java8新特性之---CompletableFuture的系统讲解和实例演示(使用CompletableFuture构建异步应用)
传统单线程环境下,调用函数是同步的,必须等待程序返回结果后,才可进行其他处理。因此为了提高系统整体的并发性能,引入了异步执行~
YourBatman
2019/09/03
3.8K0
【小家java】Java8新特性之---CompletableFuture的系统讲解和实例演示(使用CompletableFuture构建异步应用)
手把手教学妹CompletableFuture异步化,性能关系直接起飞!
由于 JDK1.5 Futrure 的 get 方法获取任务结果必须阻塞等待,Google 看不下去了,开发了 Guava 库
JavaEdge
2021/04/19
1.3K0
手把手教学妹CompletableFuture异步化,性能关系直接起飞!
JUC系列(十一) | Java 8 CompletableFuture 异步编程
在Java中CompletableFuture用于异步编程,异步通常意味着非阻塞,可以使我们的任务单独运行在与主线程分离的其他线程中,并且通过回调可以在主线程中得到异步任务的执行状态,是否完成,和是否异常等信息。
宁在春
2022/10/31
5710
JUC系列(十一) | Java 8 CompletableFuture 异步编程
Java8新的异步编程方式 CompletableFuture(三)
前面两篇文章已经整理了CompletableFuture大部分的特性,本文会整理完CompletableFuture余下的特性,以及将它跟RxJava进行比较。
fengzhizi715
2018/08/24
2.4K0
Java CompletableFuture 详解
Future是Java 5添加的类,用来描述一个异步计算的结果。你可以使用isDone方法检查计算是否完成,或者使用get阻塞住调用线程,直到计算完成返回结果,你也可以使用cancel方法停止任务的执行。
Erwin
2021/04/19
1.6K0
Java8异步编程就是拽
runAsync方法可以在后台执行异步计算,但是此时并没有返回值。持有一个Runnable对象。
架构师修炼
2020/10/23
6940
相关推荐
JUC并发—13.Future模式和异步编程简介
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验