Java多线程开发工具之CompletableFuture的应用详解

做Java编程,难免会遇到多线程的开发,但是JDK8这个CompletableFuture类很多开发者目前还没听说过,但是这个类实在是太好用了,了解它的一些用法后相信你会对它爱不释手(呸渣男,咋对谁都爱不释手呢),好了我先简单举个列子,告诉你用它有多好。Single Dog拿一个Appointment来举个列子,如下:

/**
     * 女神化完妆之后,还需要一小会选衣服,不过分吧。
     * 也就是说我们现在有2个异步任务,第一个是化妆,第二个是选衣服。
     * 选衣服要在化妆完成之后进行,这两个任务是串行
     */
    public static void main(String[] args) {
        // 线程池我前面的文章聊过,怎么配置可以去了解一下
       ThreadPoolExecutor threadPool= new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        //任务1
        CompletableFuture<String> makeUpFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "-女神,开始化妆了");
            try {
                // 化妆的时间
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "化妆完毕了。";
        }, threadPool);
       //任务2,makeUp是调用方,意思是makeUpFuture执行完后再执行
        CompletableFuture<String> dressFuture = makeUpFuture.thenApply((result) -> {
            System.out.println(Thread.currentThread().getName() + "-女神" + result + "我开始选衣服啦,好了叫你!");
            try {
                // 换衣服的时间
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return result + "衣服也选好了,走出去玩吧!";
        });
        dressFuture.thenAccept((result) -> {
            System.out.println(Thread.currentThread().getName() + "-" + result);
        });
    }

上面的2个任务也可以理解为我们开发中要实现的不同功能,看明白前面的列子了吧?用它来写多线程运用的多丝滑。那我们就先讲一下它的核心的静态的方法,推荐用它的静态方法不要直接new对象。

1:无返回值的静态方法:

​public static CompletableFuture<Void> runAsync(Runnable runnable)。

public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) 。

上面一个2个方法,如果没有指定Executor就使用默认的ForkJoinPool.commonPool()线程池,如果指定线程池就使用指定的。

2:有返回值的方法

​public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

如果开始的代码你还看不懂那介绍了上面的几个方法就先小试牛刀一下:

ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
​
        CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            int i = 10 / 2;
            System.out.println("运行的结果是:" + i);
        }, threadPool);
​
        CompletableFuture future = CompletableFuture.supplyAsync(() -> {
                    try {
                        Thread.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "Hello World";
                }, threadPool);
        System.out.println(future.get());

好了讲过它的使用方法了那我们就聊一下它的几个使用的场景,开发中这写场景应该会使用到。

​1:执行任务 A,执行任务B,待任务B执行完成后,用B的返回值区执行任务C。

ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() ->
        {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("执行任务A");
            return "任务A";
        }, executor);
        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务B");
            return "任务B";
        }, executor);
        CompletableFuture<String> futurec = futureB.thenApply((b) -> {
            System.out.println("执行任务C");
            System.out.println("参数:" + b);
            return "a";
        });
        System.out.println(futurec.get());

​运行结果,注意我上面没说B一定要在A执行以后执行。

场景2:多个任务串联执行,下一个任务的执行依赖上一个任务的结果,每个任务都有输入和输出。

ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        CompletableFuture futureA = CompletableFuture.supplyAsync(() -> "Hello", executor);
        CompletableFuture futureB = futureA.thenApply((a) -> a + " World");
        CompletableFuture futureC = futureB.thenApply((b) -> b);
        System.out.println(futureC.join());

​输出结果,开发中的经典场景输出:

​场景3:thenCombineAsync 联合 futureA和futureB的返回结果,然后在返回相关的数据

ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> 10, executor);
        CompletableFuture<Integer> futureB = CompletableFuture.supplyAsync(() -> 20, executor);
        CompletableFuture futureC = futureA.thenCombineAsync(futureB, (r1, r2) -> {
            System.out.println("r1的值为:" + r1 + ":r2的值为:" + r2);
            return r1 + r2;
        });
        System.out.println(futureC.get());

​结果输出:

好了聊完几个场景那就写一个在开发中的经典运用。

ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 10, 10, TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        System.out.println("start...");
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品信息1");
            return "future1";
        }, executor);
​
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品信息2");
            return "future2";
        }, executor);
​
        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品信息3");
            return "future3";
        }, executor);
​
        final CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(future1, future2, future3);
        voidCompletableFuture.get();
        System.out.println("end...future1的结果:" + future1.get() + ",future2的结果:" + future2.get() + ",future3的结果:" + future3.get());

​输出结果

​这个经典的应用相信你可以在你的开发中进行套用,然后灵活的运用。当然这个类还有很多的方法,我这里只写了部分介绍了部分场景作为一个引子,如果想了解它的更多的应用可以看它的API的文档。

到此这篇关于Java多线程开发工具之CompletableFuture的应用详解的文章就介绍到这了,更多相关Java CompletableFuture内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java8中CompletableFuture的用法全解

    目录 前言 一.创建异步任务 1.Future.submit 2.supplyAsync / runAsync 二.异步回调 1.thenApply / thenApplyAsync 2.thenAccept / thenRun 3. exceptionally 4.whenComplete 5.handle 三.组合处理 1.thenCombine / thenAcceptBoth / runAfterBoth 2.applyToEither / acceptEither / runAfter

  • Java CompletableFuture实现原理分析详解

    目录 简介 CompletableFuture类结构 CompletableFuture回调原理 CompletableFuture异步原理 总结 简介 前面的一篇文章你知道Java8并发新特性CompletableFuture吗?介绍了CompletableFuture的特性以及一些使用方法,今天我们主要来聊一聊CompletableFuture的回调功能以及异步工作原理是如何实现的. CompletableFuture类结构 1.CompletableFuture类结构主要有两个属性 pub

  • Java CompletableFuture 异步超时实现深入研究

    目录 前言 常见使用方式 存在的问题 分析 现有做法 解决方式 JDK 9 JDK 8 前言 作者:京东科技 张天赐 JDK 8 是一次重大的版本升级,新增了非常多的特性,其中之一便是 CompletableFuture.自此从 JDK 层面真正意义上的支持了基于事件的异步编程范式,弥补了 Future 的缺陷. 在我们的日常优化中,最常用手段便是多线程并行执行.这时候就会涉及到 CompletableFuture 的使用. 常见使用方式 下面举例一个常见场景. 假如我们有两个 RPC 远程调用

  • Java CompletableFuture实现多线程异步编排

    目录 一 :问题背景 二 :CompletableFuture介绍 三 :具体场景 1.0 单个任务 1.0.1 runAsync:无返回值 1.0.2 supplyAsync:有返回值 1.0.3 supplyAsync:有返回值 2.0 两个任务编排 2.0.1 thenRunAsync 2.0.2 thenAcceptAsync 2.0.3 thenApplyAsync 3.0 三任务编排 3.0.1 三任务组合 3.0.2 三任务组合二 4.0 多任务的编排 4.0.1.allOf:所有

  • java异步编程CompletableFuture使用示例详解

    目录 一.简单介绍 二.常见操作 1.使用默认线程池 2.使用自定义线程池 3.获取线程的执行结果 三.处理异步结算的结果 四.异常处理 五.组合 CompletableFuture 六.并行运行多个 CompletableFuture 七.案例 1.从多个平台获取书价格 2.从任意一个平台获取结果就返回 一.简单介绍 CompletableFuture 同时实现了 Future 和 CompletionStage 接口. public class CompletableFuture<T> i

  • Java多线程工具CompletableFuture的使用教程

    目录 前言 Future的问题 CompletableFuture应运而生 使用方式 基本使用-提交异步任务 处理上个异步任务结果 对两个结果进行选用-acceptEither 对两个结果进行合并-thenCombine, thenAcceptBoth 异常处理 案例 大量用户发送短信|消息 并发获取商品不同信息 问题 thenRun和thenRunAsync有什么区别 handle和exceptional有什么区别 最后 前言 Future的问题 写多线程程序的时候,可以使用Future从一个

  • Java中CompletableFuture 的详细介绍

    目录 1.概述 1.0 创建 CompletableFuture 的对象的工厂方法 1.1 non-async 和 async 区别 1.1.1 non-async 示例:注册 action 的时候任务可能已经结束 1.1.2 non-async 示例:注册 action 的时候任务未完成 1.2 Run 类方法 1.3 Accept 类方法 1.4 Apply 类方法 2 单个任务执行完成后执行一个动作(action) 2.0 示例 exceptionally 3 两个任务执行编排 4 多个任

  • Java多线程开发工具之CompletableFuture的应用详解

    做Java编程,难免会遇到多线程的开发,但是JDK8这个CompletableFuture类很多开发者目前还没听说过,但是这个类实在是太好用了,了解它的一些用法后相信你会对它爱不释手(呸渣男,咋对谁都爱不释手呢),好了我先简单举个列子,告诉你用它有多好.Single Dog拿一个Appointment来举个列子,如下: /** * 女神化完妆之后,还需要一小会选衣服,不过分吧. * 也就是说我们现在有2个异步任务,第一个是化妆,第二个是选衣服. * 选衣服要在化妆完成之后进行,这两个任务是串行

  • Java多线程之线程池七个参数详解

    ThreadPoolExecutor是JDK中的线程池实现,这个类实现了一个线程池需要的各个方法,它提供了任务提交.线程管理.监控等方法. 下面是ThreadPoolExecutor类的构造方法源码,其他创建线程池的方法最终都会导向这个构造方法,共有7个参数:corePoolSize.maximumPoolSize.keepAliveTime.unit.workQueue.threadFactory.handler. public ThreadPoolExecutor(int corePoolS

  • Java多线程通讯之wait,notify的区别详解

    下面通过代码给大家介绍java多线程通讯之wait notify的区别,具体内容如下所示: class Res{ public String username; public String sex; } class Out extends Thread{ Res res; public Out(Res res){ this.res=res; } @Override public void run() { //写操作 int count=0; while (true){ // synchroniz

  • Python 开发工具PyCharm安装教程图文详解(新手必看)

    PyCharm是由JetBrains打造的一款Python IDE,VS2010的重构插件Resharper就是出自JetBrains之手. 同时支持Google App Engine,PyCharm支持IronPython.这些功能在先进代码分析程序的支持下,使 PyCharm 成为 Python 专业开发人员和刚起步人员使用的有力工具. PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试.语法高亮.Project管理.代码跳

  • Java本地缓存工具之LoadingCache的使用详解

    目录 前言 环境依赖 代码 演示一下 总结 前言 在工作总常常需要用到缓存,而redis往往是首选,但是短期的数据缓存一般我们还是会用到本地缓存.本文提供一个我在工作中用到的缓存工具,该工具代码为了演示做了一些调整.如果拿去使用的话,可以考虑做成注入Bean对象,看具体需求了. 环境依赖 先添加maven依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</arti

  • Java Web开发中过滤器和监听器使用详解

    目录 1 Filter 1.1 Filter简介 1.2 Filter的快速入门 1.2.1 创建Filter类 1.2.2 访问index.jsp 1.3 Filter的拦截路径的配置 1.4 过滤器链 1.4.1 过滤器链简介 1.4.2 过滤器链的例子 2 Listener 2.1 概念 2.2 监听器的使用 1 Filter 1.1 Filter简介 Filter表示过滤器,是JavaWeb三大组件(Servlet.Filter.Listener)之一. 过滤器可以把资源的请求拦截下来,

  • Java多线程之并发编程的核心AQS详解

    目录 一.AQS简介 1.1.AOS概念 1.2.AQS的核心思想 1.3.AQS是自旋锁 1.4.AQS支持两种资源分享的方式 二.AQS原理 2.1.同步状态的管理 2.2.等待队列 2.3.CLH队列中的结点 2.4.队列定义 2.5.AQS底层的CAS机制 2.6.通过ReentrantLock理解AQS 三.AQS方法 3.1.用户需要自己重写的方法 3.2.AQS 提供的一系列模板方法 3.3.acquire(int)方法 3.4.release(int)方法 3.5.acquire

  • Java多线程中线程间的通信实例详解

    Java多线程中线程间的通信 一.使用while方式来实现线程之间的通信 package com.ietree.multithread.sync; import java.util.ArrayList; import java.util.List; public class MyList { private volatile static List list = new ArrayList(); public void add() { list.add("apple"); } publ

  • java树结构stream工具类的示例代码详解

    菜单实体类 package com.example.demo.entity; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @Data @Builder @AllArgsConstructor @NoArgsConstructor public class Menu { /**

  • Java多线程异步调用性能调优方法详解

    目录 概述 同步调用和异步调用 Future类图 Future的不足 代码 代码地址 Test PaymentService CheckService OrderService 总结 概述 大型电商公司的支付聚合服务都有这类的场景: 调用校验服务校验待生成的订单是否合法 订单服务生成订单(校验服务和订单服务没有依赖关系) 调用1和2,支付服务实现支付核心的功能 结合步骤1至3完成支付服务的聚合调用 ​假如步骤1的耗时5秒,步骤2的耗时3秒,步骤3的耗时2秒,如果你是架构师,要求:​ 1.请实现微

随机推荐