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.43return 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.rhkb.cn/news/237119.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

debian12部署Gitea服务之二——部署git-lfs

Debian安装gitlfs: 先更新下软件包版本 sudo apt update 安装 sudo apt install git-lfs 验证是否安装成功 git lfs version cd到Gitea仓库目录下 cd /mnt/HuHDD/Git/Gitea/Repo/hu/testrepo.git 执行lfs的初始化命令 git lfs install客户机Windows端在官网下载并安装Git-Lfs 再…

Elasticsearch windows开箱即用【记录】

一、准备工作 安装ES之前要在本机安装好JDK&#xff0c;对应的兼容性见官网链接&#xff1a;https://www.elastic.co/cn/support/matrix ES官网链接&#xff1a;https://www.elastic.co/cn/, 我本机安装的是JDK8&#xff0c;测试使用的是7.3.0版本的ES和Kibana。 1、首先去…

iOS Universal Links(通用链接)详细教程

一&#xff1a;Universal Links是用来做什么的&#xff1f; iOS9.0推出的用于应用之间跳转的一种机&#xff0c; 通过一个https的链接启动app。如果手机有安装需要启动的app&#xff0c;可实现无缝跳转。如果没有安装&#xff0c;会打开网页。 实现场景&#xff1a;微信链接无…

Linux中快速搭建RocketMQ测试环境

必要的文件下载 为什么选择RocketMQ | RocketMQ x86_64位JDK下载0jdk/8u391-b13 rocketmq二进制包下载-rocketmq-all-5.1.4-bin-release.zip 编译好的直接可用的dashboard【rocketmq-dashboard-1.0.0.jar】请在文章顶部下载 dashboard配套的配置文件【application.propert…

【2024系统架构设计】 系统架构设计师第二版-通信系统架构设计理论与实践

目录 一 通信系统网络架构 二 网络构建的关键技术 三 网络构建和设计方法 四 案例分析 注:本节内容可作为知识储备,做一个基本的了解即可。

qt-C++笔记之QProcess

qt-C笔记之QProcess code review! 文章目录 qt-C笔记之QProcess零.示例&#xff1a;QProcess来执行不带参数的系统命令ls并打印出结果一.示例&#xff1a;QProcess来执行系统命令ls -l命令并打印出结果说明 二.示例&#xff1a;QProcess来执行系统命令ls -l命令并打印出结果&…

Android14实战:打破音频默认重采样的限制(五十二)

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

spark中Rdd依赖和SparkSQL介绍--学习笔记

1&#xff0c;RDD的依赖 1.1概念 rdd的特性之一 相邻rdd之间存在依赖关系&#xff08;因果关系&#xff09; 窄依赖 每个父RDD的一个Partition最多被子RDD的一个Partition所使用 父rdd和子rdd的分区是一对一&#xff08;多对一&#xff09; 触发窄依赖的算子 map()&…

Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战

文章目录 PreCode基础工程启动类切入口事件 发布事件同步 Listener异步Listener增加EnableAsync增加 Async 测试 Pre Spring Boot - Application Events 的发布顺序_ApplicationStartingEvent Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEv…

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

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

LeetCode 232.用栈实现队列(详解) (๑•̌.•๑)

题目描述&#xff1a; 解题思路&#xff1a; 创建两个栈&#xff0c;一个用于入数据&#xff0c;一个用于出数据。分别是pushST和popST; 1.如果是入数据就直接入进pushST 2.如果是出数据&#xff0c;先检查popST中有无数据&#xff0c;如果有数据&#xff0c;就直接出。如果没…

2024年中职网络安全——Windows操作系统渗透测试(Server2105)

Windows操作系统渗透测试 任务环境说明&#xff1a; 服务器场景&#xff1a;Server2105服务器场景操作系统&#xff1a;Windows&#xff08;版本不详&#xff09;&#xff08;封闭靶机&#xff09;需要环境加Q 目录 1.通过本地PC中渗透测试平台Kali对服务器场景进行系统服务…

ubuntu安装mysql(tar.xz)

0:本机Ubuntu的版本为 腾讯云 18.04 1&#xff1a;下载地址 MySQL &#xff1a;&#xff1a; 下载 MySQL 社区服务器 2&#xff1a;上传文件到服务器 3:解压 sudo sumv mysql-8.2.0-linux-glibc2.17-x86_64-minimal.tar.xz /usrtar -xvf mysql-8.2.0-linux-glibc2.17-x86_6…

逆变器3前级推免(高频变压器)

一节电池标压是在2.8V—4.2V之间&#xff0c;所以24V电压需要大概七节电池串联。七节电池电压大概在19.6V—29.4V之间。 从24V的电池逆变到到220V需要升压的过程。那么我们具体需要升压到多少&#xff1f; 市电AC220V是有效值电压&#xff0c;峰值电压是220V*1.414311V 如果…

Ubuntu下AI4Green开源ELN服务的简单部署

主部署程序&#xff1a;AI4Green 配置参考这篇文档&#xff1a;AI4Green开源ELN&#xff08;电子实验记录本&#xff09;-CSDN博客 流量转发和负载均衡&#xff1a;使用Nginx 配置参考这篇文档&#xff1a;Nginx负载均衡-CSDN博客 SSL配置部分参考这篇文档&#xff1a; 设置…

Android Lint的使用

代码检查方式一&#xff1a; Android Studio使用Lint进行代码检查 找到Analyze目录下的Inspect Code检查代码选项点击然后弹出下面这个框框&#xff0c;在这个列表选项中我们可以选择Inspect Code的范围&#xff0c;点击OK 待分析完毕后&#xff0c;我们可以在Inspection栏目中…

WPF XAML(一)

一、XAML的含义 问&#xff1a;XAML的含义是什么&#xff1f;为什么WPF中会使用XAML&#xff1f;而不是别的&#xff1f; 答&#xff1a;在XAML是基于XML的格式&#xff0c;XML的优点在于设计目标是具有逻辑性易读而且简单内容也没有被压缩。 其中需要提一下XAML文件在 Visu…

Java并查集设计以及路径压缩实现

Java全能学习面试指南&#xff1a;https://javaxiaobear.cn 并查集是一种树型的数据结构 &#xff0c;并查集可以高效地进行如下操作&#xff1a; 查询元素p和元素q是否属于同一组合并元素p和元素q所在的组 1、并查集的结构 并查集也是一种树型结构&#xff0c;但这棵树跟我们之…

Unity C# 枚举多选

枚举多选 &#x1f96a;例子&#x1f354;判断 &#x1f96a;例子 [System.Flags]public enum TestEnum{ None 0,Rooms 1 << 1,Walls1<<2,Objects1<<3,Slabs 1 << 4,All Rooms|Walls|Objects|Slabs}&#x1f354;判断 TestEnum test TestEnum.R…

C++ 手写堆 || 堆模版题:堆排序

输入一个长度为 n 的整数数列&#xff0c;从小到大输出前 m 小的数。 输入格式 第一行包含整数 n 和 m 。 第二行包含 n 个整数&#xff0c;表示整数数列。 输出格式 共一行&#xff0c;包含 m 个整数&#xff0c;表示整数数列中前 m 小的数。 数据范围 1≤m≤n≤105 &…