JUC之CompletableFuture

Future接口理论

Future接口定义了异步任务执行的一些方法,包括异步任务执行结果,异步任务执行是否中断,异步任务是否完毕等。

Future接口常用实现类FutureTask异步任务

        FutureTask<String> futureTask = new FutureTask<String>( () -> {
            System.out.println(Thread.currentThread().getName()+"\t -----come in");
            try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
            return "task over";
        });
        Thread t1 = new Thread(futureTask, "t1");
        t1.start();

CompletableFuture

CompletableFuture对Future的改进

  • CompletableFuture异步线程发生异常,不会影响到主线程,用来记录日志特别方便。
  • CompletableFuture出现的原因:Future的get方法是阻塞方法,当异步线程计算完成之前一直会阻塞,isDone()方法判断异步线程又特别消耗CPU资源。对于真正的异步处理我们希望传入回调函数,在Future结束时,自动调用该回调函数。这样我们就不用等待结果 。
  • CompletableFuture提供了一种观察者模式,可以让任务完成后通知监听的一方。
    在这里插入图片描述

CompletionStage

  • CompltionStage是异步执行的一个阶段。一个阶段执行完成之后可能触发另一个阶段。
  • 一个阶段的执行可以是一个Function,Comsumer或者Runnable。比如
 stage.thenApply(x -> square(x)).thenAccept(×->System.out.print(x)).thenRun(( ->system.out.println())
  • 一个阶段可能会是另一个阶段完成后触发。也可能是其他多个阶段完成后触发。

CompletableFuture的方法

在这里插入图片描述
主要是runAsync和supplyAsnc方法。一个无返回值。一个有返回值。

CompletableFuture的优点

  • 异步任务执行完成后,会自动调用某个对象的方法
  • 异步任务出异常后,会自动调用某个对象的方法
  • 主线程设置好回调后,不用关心异步任务的执行。异步任务之间可以顺序执行。

案例 - 前言

join和get的区别。get必须处理异常。join不需要处理异常
jdk8新特性: lambda表达式,stream流,chain链式调用,函数式编程
在这里插入图片描述
有参数,有返回值:Function
有参数,无返回值:Consume, BiConsumer(两个参数)
无参数,有返回值:Supplier
无参数,无返回值:Runnable

案例-从电商网站的比价需求

原来的写法,串行的方式

    /**
     * step by step 一家家搜查
     * List<NetMall> ----->map------> List<String>
     * @param list
     * @param productName
     * @return
     */
    public static List<String> getPrice(List<NetMall> list,String productName)
    {
        //《mysql》 in taobao price is 90.43
        return list
                .stream()
                .map(netMall ->
                        String.format(productName + " in %s price is %.2f",
                                netMall.getNetMallName(),
                                netMall.calcPrice(productName)))
                .collect(Collectors.toList());
    }

使用CompletableFuture,异步的方式

 /**
     * List<NetMall> ----->List<CompletableFuture<String>>------> List<String>
     * @param list
     * @param productName
     * @return
     */
    public static List<String> getPriceByCompletableFuture(List<NetMall> list,String productName)
    {
        return list.stream().map(netMall ->
                CompletableFuture.supplyAsync(() -> String.format(productName + " in %s price is %.2f",
                netMall.getNetMallName(),
                netMall.calcPrice(productName))))
                .collect(Collectors.toList())
                .stream()
                .map(s -> s.join())
                .collect(Collectors.toList());
    }

耗时:比串行的方式快得多!!!

CompletableFuture 常用方法

获得结果和触发计算

获得结果:

  • public T get() 一直等
  • public T get(long timeout,TimeUnit unit) 过时不候,到了时间没拿到结果会报异常
  • public T join():join和get都是用来获取CompletableFuture异步之后的返回值。join是unchecked异常(即运行时异常)。get是checked异常(经过检查的异常)
  • public T getNow(T valuelfAbsent):没有计算完,给我默认的结果。计算完,返回实际的结果。

主动触发计算:

  • public boolean complete(T value) 如果CompletableFuture没有完成,将get结果修改为value,返回值为true。如果完成了,不修改get,返回值为false.
public class CompletableFutureTest {

  public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
      CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
          try {
              Thread.sleep(2000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          return "hello CompletableFuture";
      });

      System.out.println(completableFuture.getNow("心急吃不了热豆腐"));
      System.out.println(completableFuture.get());
      System.out.println(completableFuture.get(1500, TimeUnit.MILLISECONDS));
      System.out.println(completableFuture.join());
      System.out.println(completableFuture.complete("未雨绸缪")+"\t"+completableFuture.join());

  }
}

对计算结果进行处理

thenApply(常用)

两个计算结果存在依赖关系,这两个线程串行化。
出现异常,直接跳到whenComplete和exceptionally执行。(不再执行后续的thenApply)

public class CompletableFutureTest2 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 6;
        },executorService).thenApply((r)-> {
            int i=2/0;
            return r * 5;
        }).thenApply((r)-> {
            System.out.println(r);
            return r - 2;
        }).whenComplete((v, e) -> {
            System.out.println("计算结果:"+v);
        }).exceptionally(e -> {
            System.out.println(e.getMessage());
            System.out.println(e);
            return null;
        });
        System.out.println("============主线程==========");
        executorService.shutdown();
    }
}

handle

计算机结果存在依赖关系,两个线程串行化
handle出现异常,会往下一个handle走,同时也会走到whenComplete和exceptionally

public class CompletableFutureTest2 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 6;
        },executorService).handle((r,e)-> {
            int i=2/0;
            return r * 5;
        }).handle((r,e)-> {
            System.out.println(r);
            return r - 2;
        }).whenComplete((v, e) -> {
            System.out.println("计算结果:"+v);
        }).exceptionally(e -> {
            System.out.println(e.getMessage());
            System.out.println(e);
            return null;
        });
        System.out.println("============主线程==========");
        executorService.shutdown();
    }
}

exceptionally相当于try catch
whenComplete和handler相当于try finally
在这里插入图片描述

对计算结果进行消费

接受任务的处理结果,消费处理。thenAccept无返回结果。(thenApply是有返回结果的)

public class CompletableFutureTest3 {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(()->{
            return 3;
        }).thenApply(r->{
            return r*8;
        }).thenApply(r->{
            return r/2;
        }).thenAccept(r-> System.out.println(r));
        System.out.println(CompletableFuture.supplyAsync(()->"6666").thenRun(()->{}).join());
        System.out.println(CompletableFuture.supplyAsync(()->"6666").thenAccept(r-> System.out.println(r)).join());
        System.out.println(CompletableFuture.supplyAsync(()->"6666").thenApply(r->r+"9999").join());
    }
}

12
null
6666
null
66669999

对计算速度进行选用与对计算结果进行合并

applyToEither:谁快用谁
thenCombine: 两个completionStage任务都完成后,将结果交给thenCombine。先完成的先等着,等待其他分支任务。

public class CompletableFutureTest4 {
    public static void main(String[] args) {
        CompletableFuture<String> first = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "1号选手";
        });
        CompletableFuture<String> second = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "2号选手";
        });
        CompletableFuture<String> result = first.applyToEither(second, r -> r + "is winner");
        CompletableFuture<String> res = first.thenCombine(second, (x, y) -> x + y);
        System.out.println(result.join());
        System.out.println(res.join());
    }
}

并行执行

allOf():当所有给定的CompletableFuture完成时, 返回一个新的CompletableFuture
anyOf():当任何一个给定的CompletableFuture完成时,返回一个新的CompletableFuture

	public static void testAllOf(){
        CompletableFuture<String> future1 = CompletableFuture.runAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("future1执行完成");
        });

        CompletableFuture<String> future2 = CompletableFuture.runAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("future2执行完成");
        });

        CompletableFuture<Void> all = CompletableFuture.allOf(future1, future2);
			try {
            all.get(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

completableFuture和线程池说明

以thenRun和thenRunAsync为例,有什么区别?

  • 没有传入自定义线程池,默认是ForkJoinPool.
  • 如果第一个执行的任务传入了一个自定义线程池,调用thenRun执行第二个任务,则第一个和第二个都是用自定义的线程池。
  • 如果第一个执行的任务传入了一个自定义线程池,调用thenRunAsyn执行第二个任务,则第一个用自定义。第二个用ForkJoinPool(后面也都是ForkJoinPool)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/317542.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业网盘:实现数据跨境传输,助力企业出海的必备工具

今年是“一带一路”十周年。在这十年间&#xff0c;中国和“一带一路”共建国家携手并行&#xff0c;贸易持续增长发展。在如今经济全球化的大方向下&#xff0c;跨国经济合作将会是各国共识。 目前&#xff0c;中外合作企业、跨境企业已成为国际贸易发展趋势。不过&#x…

扩展欧几里得算法

文章目录 扩展欧几里得算法的内容及证明扩展欧几里得算法的代码实现扩展欧几里得算法的用途 本文的问题场景中&#xff0c;涉及到的变量均为整数。 扩展欧几里得算法的内容及证明 贝祖等式&#xff1a; a x b y g c d ( a , b ) c axby gcd(a, b) c axbygcd(a,b)c 其中 …

PLC数组队列搜索FC(SCL代码+梯形图程序)

根据输入数据搜索输入数据队列中和输入数据相同的数,函数返回其所在队列的位置。这里我们需要用到博途PLC的数组指针功能,有关数组指针的详细使用方法,可以参考下面文章: 博途PLC数组指针: https://rxxw-control.blog.csdn.net/article/details/134761364 区间搜索FC …

软件测试|Git:fatal: refusing to merge unrelated histories错误分析与解决

问题介绍 在使用Git时&#xff0c;有时我们可能会遇到以下错误消息&#xff1a; fatal: refusing to merge unrelated histories这个错误通常发生在尝试合并两个不相关的Git仓库历史时。在本文中&#xff0c;我们将详细解释为什么会出现这个错误以及如何解决它。 问题分析 …

代码随想录算法训练营第四天 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

代码随想录算法训练营第四天 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II 文章目录 代码随想录算法训练营第四天 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II1 Le…

CSS样式学习

html超文本传输标签&#xff0c;属性等权重 outline 标签轮廓 <input type"text"> <textarea cols"30" rows"10"></textarea> outline: none; 表示无轮廓 &#xff08;开发时用的比较多&#xff09; CSS 轮廓&#xff…

大创项目推荐 深度学习疫情社交安全距离检测算法 - python opencv cnn

文章目录 0 前言1 课题背景2 实现效果3 相关技术3.1 YOLOV43.2 基于 DeepSort 算法的行人跟踪 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习疫情社交安全距离检测算法 ** 该项目较为新颖&#xff0c;适合作为竞赛…

【踩坑】flask_uploads报错cannot import name ‘secure_filename‘

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 背景说明 截至目前&#xff0c;用新版的flask实现文件上传(用到flask_uploads库)&#xff0c;会出现这个问题。 问题原因 版本问题&#xff0c;新的werkzeug已经把secure_filename的位置改了。 解决方法 手动修改…

第23集《佛法修学概要》

庚二、不偷盗分五&#xff1a;辛一、解释名义&#xff1b;辛二、具缘成犯&#xff1b;辛三、犯戒轻重&#xff1b;辛四、开缘情况&#xff1b;辛五、持犯得失 请大家打开讲义第六十五页。我们看庚二、不偷盗。 这一科&#xff0c;我们讲到人天乘的法门。五戒十善为什么叫人天…

【数模百科】距离美赛还有20天,不要忘了阅读往年获奖论文(附04-23年美赛获奖论文)

之前发了很多数模相关的知识&#xff0c;受到了一些人的关注&#xff0c;也有很多人私下问我&#xff0c;距离美赛还有20几天了&#xff0c;还来不来得及。 对此我想说&#xff0c; 来不来得及重要吗&#xff1f; 你名都报了&#xff0c;钱也交了&#xff0c;还是笔不小的钱…

OpenGL 网格拾取坐标(Qt)

文章目录 一、简介二、代码实现三、实现效果参考资料一、简介 有时候我们希望通过鼠标来拾取某个网格中的坐标,这就涉及到一个很有趣的场景:光线投射,也就是求取一条射线与网格的交点,这里如果我们采用普通遍历网格中的每个面片的方式,当网格的面片数据量很大时计算效率就…

H7303 无电感,线性恒流,低压差,大电流,车灯/台灯 9V 12V 24V 30V

线性恒流芯片是一种用于控制电流的电子元件&#xff0c;通常用于驱动LED等器件。它的工作原理是通过维持输出电流的恒定来保持被驱动器件的亮度或功率稳定。 具体来说&#xff0c;线性恒流芯片会监测输出电流并调整电压以保持恒定的电流流过被驱动器件。以下是其基本工作步骤&…

国内镜像:极速下载编译WebRTC源码(For Android/Linux/IOS)(二十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

基础数据结构第九期 堆(数组+STL)

前言 堆是一种重要的数据结构&#xff0c;因此应该熟练掌握。 一、堆的基本概念 堆的基本&#xff1a; 堆的结构实际上是一棵完全二叉树&#xff0c;堆可以分为大根堆和小根堆 大根堆&#xff1a; 小根堆&#xff1a; 堆的储存&#xff1a; 若节点小标为i&#xff0c;则左子…

常用计算电磁学算法特性与电磁软件分析

常用计算电磁学算法特性与电磁软件分析 参考网站&#xff1a; 计算电磁学三大数值算法FDTD、FEM、MOM ADS、HFSS、CST 优缺点和应用范围详细教程 ## 基于时域有限差分法的FDTD的计算电磁学算法&#xff08;含Matlab代码&#xff09;-框架介绍 参考书籍&#xff1a;The finite…

three.js 学习笔记(学习中1.10更新) |

文章目录 three.js 学习笔记基础概念透视相机 第一个three.js应用threejs画布尺寸和布局canvas画布宽高度动态变化 坐标辅助器 THREE.AxesHelper实现动画效果requestAnimationFrame时间相关属性和方法 THREE.Clock类 相机控件 轨道控制器OrbitControls 灯光点光源点光源辅助观察…

基于python舆情分析可视化系统+情感分析+爬虫+机器学习(源码)✅

大数据毕业设计&#xff1a;Python招聘数据采集分析可视化系统✅ 毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&…

怎么安装IK分词器

.安装IK分词器 1.在线安装ik插件&#xff08;较慢&#xff09; # 进入容器内部 docker exec -it elasticsearch /bin/bash ​ # 在线下载并安装 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elastics…

4.4 千万 TOKEN 心理咨询语料库发布,专为大模型,让人工智能技术更好的服务人

2023 年&#xff0c;全网火爆聊天机器人&#xff0c;不同行业企业开始探索应用大模型于垂直领域&#xff0c;当算法和算力已经被证明是行之有效的&#xff0c;那么重头戏就是数据了&#xff0c;Chatopera 近日发布了心理咨询行业的又一大规模语料 - 包含 4.4 千万 TOKEN 的多轮…

设计模式之策略模式【行为型模式】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档> 学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某…