把之前CompletableFuture留下的坑给填上。 (中)

简介: 把之前CompletableFuture留下的坑给填上。 (中)

按理来说也就是可以用了。

但是如果你不需要返回值,它还提供了这样的写法:

image.png

正常情况和异常情况分开处理。

优雅,非常优雅。

还有更牛的。

前面我们化妆的线程和化妆完成的线程不是同一个线程吗:

image.png

image.png

image.png

只需要把调用的方法从 whenComplete 改为 whenCompleteAysn 即可。

同样,这个方法也支持指定线程池:


image.png

你可以去看 CompletableFuture 里面有非常多的 Aysn 结尾的方法,大多都是干这个事儿的,以异步的形式在线程池中执行。

如果说上面的介绍让你觉得不过如此,那么再介绍一个 Future 没有的东西。

假设现在需求是这样的。

女神化完妆之后,还要花个一小会选衣服,不过分吧。

也就是说我们现在有两个异步任务,第一个是化妆,第二个是选衣服。

选衣服要在化妆完成之后进行,这两个任务是串行的,用 CompletableFuture 怎么实现呢?

我把代码贴一下,为了看起来更加直观,我没有用链式调用:

public class MainTest {
    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //任务一
        CompletableFuture<String> makeUpFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "-女神:我开始化妆了。");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "化妆完毕了。";
        }, executorService);
        //任务二(makeUpFuture是方法调用方,意思是等makeUpFuture执行完成后执行再执行)
        CompletableFuture<String> dressFuture = makeUpFuture.thenApply(makeUp -> {
            System.out.println(Thread.currentThread().getName() + "-女神:" + makeUp + "我开始选衣服啦,好了我叫你。");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return makeUp + "衣服也选好啦。靓仔,走去玩儿吧。";
        });
        //获取结果
        dressFuture.thenAccept(result -> {
            System.out.println(Thread.currentThread().getName() + "-" + result);
        });
    }
}

这样输出结果就是这样的:

image.png

符合我们的预期。

假设我们想要选衣服的时候换另外一个线程怎么办呢?

别说不知道,这不刚才教你了吗,Async 结尾的方法,得活学活用起来:

image.png

前面讲的是多个异步任务串行执行,接下来再说一下并行。

CompletableFuture 里面提供了两个并行的方法:

image.png

两个方法的入参都是可变参数,就是一个个异步任务。

allOf 顾名思义就是入参的多个 CompletableFuture 都必须成功,才能继续执行。

而 anyOf 就是入参的多个 CompletableFuture 只要有一个成功就行。

还是举个例子。

假设,我是说假设啊,我是一个海王。

算了,我假设我有一个朋友吧。

image.png

他同时追求好几个女朋友。今天他打算约小美和小乖中的一个出门玩,随便哪个都行。谁先化妆完成,就约谁。另外一个就放她鸽子。

这个场景,我们就可以用 anyOf 来模拟,于是就出现了这样的代码:

微信图片_20220428204606.png


从输出结果来看,最后和朋友约会的是小美。

都把小美约出来了,必须要一起吃个饭才行,对吧。

那么这个时候朋友问:小美,你想吃点什么呢?

小美肯定会回答:随便,就行,无所谓。

听到这样的回答,朋友心里就有底了,马上给出了一个方案:我们去吃沙县小吃或者黄焖鸡吧,哪一家店等的时间短,我们就去吃哪一家。

image.png

于是上面的代码,就变成了这样:

微信图片_20220428204606.png


image.png

我把代码都放这里,你粘过去就能跑起来:

public class MainTest {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        CompletableFuture<String> xiaoMei = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "-小美:我开始化妆了,好了我叫你。");
            try {
                int time = ThreadLocalRandom.current().nextInt(5);
                TimeUnit.SECONDS.sleep(time);
                System.out.println(Thread.currentThread().getName() + "-小美,化妆耗时:" + time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "小美:化妆完毕了。";
        }, executorService);
        CompletableFuture<String> xiaoGuai = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "-小乖:我开始化妆了,好了我叫你。");
            try {
                int time = ThreadLocalRandom.current().nextInt(5);
                TimeUnit.SECONDS.sleep(time);
                System.out.println(Thread.currentThread().getName() + "-小乖,化妆耗时:" + time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "小乖:化妆完毕了。";
        }, executorService);
        CompletableFuture<Object> girl = CompletableFuture.anyOf(xiaoMei, xiaoGuai);
        girl.thenAccept(result -> {
            System.out.println("我看最后是谁先画完呢 = " + result);
        });
        CompletableFuture<String> eatChooseOne = girl.thenApplyAsync((result) -> {
            try {
                TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return result + "这里人少,我们去吃沙县小吃吧!";
        }, executorService);
        CompletableFuture<String> eatChooseTwo = girl.thenApplyAsync((result) -> {
            try {
                TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return result + "这里人少,我们去吃黄焖鸡吧!";
        }, executorService);
        CompletableFuture.allOf(eatChooseOne, eatChooseTwo).thenAccept(result -> {
            System.out.println("最终结果:" + result);
        });
    }
}

如果你说,小孩子才做选择,大人是全部都要。

那么,你可以试着用一下 allOf,只是需要注意的是,allOf 是不带返回值的。

好了,写到这里我都感觉有点像是 API 教学了,没啥劲。所以 CompletableFuture 还有很多很多的方法,我就不一一介绍了。

目录
相关文章
|
8月前
|
Java BI API
剑指JUC原理-17.CompletableFuture(下)
剑指JUC原理-17.CompletableFuture
61 0
|
8月前
|
Java
剑指JUC原理-17.CompletableFuture(上)
剑指JUC原理-17.CompletableFuture
59 0
|
Java
CompletableFuture总结和实践
CompletableFuture被设计在Java中进行异步编程。异步编程意味着在主线程之外创建一个独立的线程,与主线程分隔开,并在上面运行一个非阻塞的任务,然后通知主线程进展,成功或者失败。
384 0
|
消息中间件 存储 Java
一网打尽异步神器CompletableFuture
最近一直畅游在RocketMQ的源码中,发现在RocketMQ中很多地方都使用到了CompletableFuture,所以今天就跟大家来聊一聊JDK1.8提供的异步神器CompletableFuture,并且最后会结合RocketMQ源码分析一下CompletableFuture的使用。
|
Java
Java并发编程:深入理解CompletableFuture
一、引言 在Java的世界中,多线程编程一直被誉为其独特优势之一,而在Java 8中引入的CompletableFuture则为这一领域提供了更加强大和灵活的工具。本文将对CompletableFuture进行深度剖析,带你领略其在多线程开发中的实力。
128 0
|
Java 开发者 Sentinel
CompletableFuture学习整理
整理的原因是在Sentinel源码中,我们可以看到很多关于CompletableFuture的thenCompose的源码。同时在业务系统里面也看到别人写过类似的代码。因此整理了一下关于CompletableFuture使用的相关类型和特性,在处理复杂耗时业务时可以选择组合使用。
228 0
CompletableFuture学习整理
|
消息中间件 Dubbo Kafka
CompletableFuture学习
前面我们已经知道CompletionService是可以解决Future带来的阻塞问题的,同时我们除了前面我们看到的take方法之外,还可以使用poll方法,这样可以使你的程序免受阻塞之苦。因为poll方法也是无阻塞性的。同时在kafka的源码中,我们如果使用消费者的话,可以看到会使用一个基于future的poll方法。同时我们可以在dubbo的新版本2.7中,可以看到其异步编程采用的就是我们要介绍的CompletableFuture。因此,我们有必要了解CompletableFuture,同时其也是真正意义上的异步编程的实现。
161 0
CompletableFuture学习
|
Java 编译器 程序员
看完这篇 final、finally 和 finalize 和面试官扯皮就没问题了(一)
final 是 Java 中的关键字,它也是 Java 中很重要的一个关键字,final 修饰的类、方法、变量有不同的含义;finally 也是一个关键字,不过我们可以使用 finally 和其他关键字结合做一些组合操作;finalize 是一个不让人待见的方法,它是对象祖宗 Object 中的一个方法,finalize 机制现在已经不推荐使用了。本篇文章,cxuan 就带你从这三个关键字入手,带你从用法、应用、原理的角度带你深入浅出理解这三个关键字。
113 0
看完这篇 final、finally 和 finalize 和面试官扯皮就没问题了(一)
|
Java Unix 编译器
看完这篇 final、finally 和 finalize 和面试官扯皮就没问题了(二)
final 是 Java 中的关键字,它也是 Java 中很重要的一个关键字,final 修饰的类、方法、变量有不同的含义;finally 也是一个关键字,不过我们可以使用 finally 和其他关键字结合做一些组合操作;finalize 是一个不让人待见的方法,它是对象祖宗 Object 中的一个方法,finalize 机制现在已经不推荐使用了。本篇文章,cxuan 就带你从这三个关键字入手,带你从用法、应用、原理的角度带你深入浅出理解这三个关键字。
165 0
看完这篇 final、finally 和 finalize 和面试官扯皮就没问题了(二)
异步神器CompletableFuture
异步神器CompletableFuture

热门文章

最新文章