【JUC】十三、CompletableFuture的常用方法

文章目录

  • 1、获得结果和触发计算
  • 2、对计算结果进行处理
  • 3、对结算结果进行消费
  • 4、CompletableFuture的thenXX和thenXXAsync
  • 5、对计算速度进行选用
  • 6、对计算结果进行合并

1、获得结果和触发计算

  • 获取任务结果
public T get()
public T get(long timeout, TimeUnit unit)
public T join()
  • 获取当前计算结果,传入缺省值。计算完成时正常返回,未计算完成时,返回传入的缺省值
public T getNow(T valueIfAbsent)

在这里插入图片描述

  • 传入value,是否打断了get方法,且再次get时,返回刚才传入的值。有点像getNow
boolean complete(T value)
//举例:
public class CompletDemo1 {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {System.out.println(Thread.currentThread().getName());try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}return "9527";});System.out.println(completableFuture.complete("completValue") + "\t" + completableFuture.join());}
}

在这里插入图片描述

2、对计算结果进行处理

结果的续传和计算,上一步的计算结果传给下一步,类比买鱼、下锅、调料,相关方法:

  • thenApply方法
  • handle方法

二者都是计算结果存在依赖关系时用的,即两个任务所在的线程串行化。区别是当某一步发生异常时:

  • thenApply叫停,不再走一下步骤
  • handle会继续走下一步
public class CompletDemo1 {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService pool = Executors.newFixedThreadPool(4);try {CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {System.out.println("11");try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}return "11";}, pool).thenApply(f -> {System.out.println("22");return f + "22";}).thenApply(f -> {System.out.println("33");return f + "33";}).whenComplete((v, e) -> {if (null == e) {System.out.println("計算完成:" + v);}}).exceptionally(e -> {e.printStackTrace();System.out.println(e.getMessage());return null;});System.out.println(Thread.currentThread().getName() + "先去处理其他任务了...");} catch (Exception e) {e.printStackTrace();} finally {pool.shutdown();}}
}

在这里插入图片描述

模拟异常:

在这里插入图片描述

换handle:

在这里插入图片描述

3、对结算结果进行消费

接收任务的执行结果,并进行消费处理,无返回结果,相关方法:thenAccept

CompletableFuture.supplyAsync(() -> 1).thenApply(f -> f + 2).thenAccept(t -> {System.out.println(t);});
//.thenAccept(System.out::println);//輸出3

对比:

在这里插入图片描述

//null(因为thenRun无返回值,最后join就是null)
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenRun(() -> {}).join());
//resultA(中途任务输出的)
//null(最后join的)
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenAccept(f -> System.out.println(f)).join());
//resultA resultB
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenApply(f -> f + " resultB").join());

4、CompletableFuture的thenXX和thenXXAsync

可以发现以上整理的方法中,每个都有xxAsync方法:

在这里插入图片描述

看下源码:

在这里插入图片描述

跟进defaultExecutor,发现其来自ASYNC_POOL:

在这里插入图片描述

三目运算符,除非不支持并行,一般就是FrokJoinPool。写个试验的代码:

public class CompletableDemo4 {public static void main(String[] args) {ExecutorService pool = Executors.newFixedThreadPool(6);try {CompletableFuture<Void> completableFuture = CompletableFuture.supplyAsync(() -> {System.out.println("1号任务在" + Thread.currentThread().getName());return "1024";},pool).thenRun(() -> {System.out.println("2号任务在" + Thread.currentThread().getName());}).thenRun(() -> {try {TimeUnit.MILLISECONDS.sleep(30);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("3号任务在" + Thread.currentThread().getName());}).thenRun(() -> {try {TimeUnit.MILLISECONDS.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("4号任务在" + Thread.currentThread().getName());});System.out.println(completableFuture.join());} catch (Exception e) {e.printStackTrace();} finally {pool.shutdown();}}
}

结论:

  • 不管thenRun还是thenRunAsync,没有传入自定义的线程池时,二者都使用默认的ForkJoinPool线程池
  • 传入一个自定义线程池在任务x,则调用thenRun方法执行下一个任务时,这两个任务共用同一个线程池
  • 调用thenRunAsync方法执行执行下一个任务时,第一个用自己传入的线程池,第二个用ForkJoin线程池
  • 总之thenXX和thenXXSync就是影响到了任务是否另起炉灶(线程池)
  • 此外,有可能系统处理太快,系统优化切换规则,会出现直接使用main线程处理的现象

5、对计算速度进行选用

A和B两个任务谁先执行完,相关方法:

applyToEither(xx,xx)

示例:

public class CompletableDemo5 {public static void main(String[] args) {CompletableFuture<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {System.out.println("A come in");try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}return "playerA";});CompletableFuture<String> completableFuture2 = CompletableFuture.supplyAsync(() -> {System.out.println("B come in");try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}return "playerB";});CompletableFuture<String> result = completableFuture1.applyToEither(completableFuture2, f -> f + " is winer!");System.out.println(Thread.currentThread().getName() + "----" + "\t" + result.join());}
}

在这里插入图片描述

6、对计算结果进行合并

两个任务都完成后,最终把两个任务的结果一起交给thenCombine来处理,先完成的任务先等着,等待其他分支完成任务。

thenCombine

可链式编程,因为其返回类型还是CompletableFuture,传入:

  • 参数一:要合并的另一个CompletableFuture
  • 参数二:BiFunction,定义对两个任务的合并逻辑,比如你选择相加
public class CompletableDemo6 {public static void main(String[] args) {CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {System.out.println(Thread.currentThread().getName() + "\t --- 开始计算");try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}return 20;});CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {System.out.println(Thread.currentThread().getName()+ "\t --- 开始计算");try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {e.printStackTrace();}return 10;});CompletableFuture<Integer> result = completableFuture1.thenCombine(completableFuture2, (x, y) -> {System.out.println("---计算结果开始合并");return x + y;});System.out.println(result.join());}
}

一个2s,一个4s,先完成的先等等:

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

STM32F103C8T6——4路PWM

//main()函数前面的extern TIM_HandleTypeDef htim2;extern TIM_HandleTypeDef htim3;//main()函数内部额外添加的HAL_TIM_Base_Start_IT(&htim2);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);HAL_TIM_PWM_Start(&htim2…

013 C++ set与map的用法

前言 本文将会向你介绍set与map的主要用法 set详解 int main() {set<string> s;vector<string> v { "Fan1","Fan2", "Fan3", "Fan4" };for (auto e : v){s.insert(e);}string input;while (cin >> input){if (s.…

数组题目:118. 杨辉三角 、 119. 杨辉三角 II 、661. 图片平滑器 、598. 范围求和 II 、 419. 甲板上的战舰

118. 杨辉三角 思路&#xff1a; 找规律&#xff0c;每一行的第一个元素和最后一个元素都是1&#xff0c;其中中间需要改变的数找对应的规律 比如第二行&#xff08;从0开始&#xff09;的2&#xff0c;是dp[1][0] dp[1][1]。类似的找出对应的规律 代码&#xff1a; clas…

【网络安全】-常见的网站攻击方式详解

文章目录 介绍1. SQL 注入攻击攻击原理攻击目的防范措施 2. 跨站脚本攻击&#xff08;XSS&#xff09;攻击原理攻击目的防范措施 3. CSRF 攻击攻击原理攻击目的防范措施 4. 文件上传漏洞攻击原理攻击目的防范措施 5. 点击劫持攻击原理攻击目的防范措施 结论 介绍 在数字时代&a…

aspera传输方案怎么样,需要选择aspera替代方案吗

Aspera传输方案是一种高速、可靠的文件传输解决方案&#xff0c;适用于需要大规模传输大文件或数据集的企业和组织。Aspera采用UDP协议及自己开发的FASP协议进行加速传输&#xff0c;能够在高延迟、高丢包网络环境下实现稳定快速的传输。 Aspera传输方案具有以下优点&#xff1…

Selenium Grid

Selenium Grid 什么是Selenium Grid Selenium是Selenium套件的一部分,它专门用于并行运行多个测试用例在不同的浏览器、操作系统和机器上 Selenium Grid的两个版本 Grid1与Grid2两个版本的原理和基本工作方式完全相同&#xff0c;Grid2同时支持Selenium1和Selenium2&#x…

<JavaEE> Thread线程类 和 Thread的常用方法

目录 一、Thread概述 二、构造方法 三、常用方法 1.1 getId()、getName()、getState()、getPririty() 1.2 start() 1.3 isDaemon()、setDaemon() 1.4 isAlive() 1.5 currentThread() 1.6 Interrupt()、interrupted()、isInterrupted() 1.6.1 方法一&#xff1a;添加共…

stream流和方法引用

1.Stream流 1.1体验Stream流【理解】 案例需求 按照下面的要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素把集合中所有以"张"开头的元素存储到一个新的集合把"张"开头的集合中的长度为3的元素存储到一个新的集合遍历上一步得到的集…

SIT65HVD75,可替代SN65HVD75,3.0~5.5V 供电,ESD 15kV HBM,20Mbps 半双工 RS485/RS422 收发器

SIT65HVD75 是一款 3.0V~5.5V 电源供电、总线端口 ESD 保护能力 HBM 达到 15kV 以上、 总线耐压范围达到 15V 、半双工、低功耗&#xff0c;功能完全满足 TIA/EIA-485 标准要求的 RS-485 收发 器。 SIT65HVD75 包括一个驱动器和一个接收器&#xff0c;两者均可…

模板上新|2023年10月DataEase模板市场上新动态

DataEase开源数据可视化分析平台于2022年6月正式发布模板市场&#xff08;https://dataease.io/templates/&#xff09;。模板市场旨在为DataEase用户提供专业、美观、拿来即用的仪表板模板&#xff0c;方便用户根据自身的业务需求和使用场景选择对应的仪表板模板&#xff0c;并…

计算机网络——数据链路层-数据链路层概述(介绍、三个重要问题、使用广播信道的数据链路层、其他问题)

目录 介绍 三个重要问题 封装成帧 差错检测 可靠传输 使用广播信道的数据链路层 其他问题 介绍 本篇对数据链路层进行概述&#xff0c;我们首先来看看数据链路层在网络体系结构中的地位&#xff1a; 主机H1给主机H2发送数据&#xff0c;中间要经过三个路由器和电话网、…

单片机学习10——独立按键

独立按键输入检测&#xff1a; #include<reg52.h>sbit LED1P1^0; sbit KEY1P3^4;void main() {KEY11;while(1){if(KEY10) //KEY1按下{LED10; //LED1被点亮}else{LED11;}} } 按键 #include<reg52.h>#define uchar unsigned char #define uint unsigned intsbit …

使用Postman如何在接口测试前将请求的参数进行自定义处理

1、前言 当我们使用 Postman 进行接口测试时&#xff0c;对于简单的不需要处理的接口&#xff0c;直接请求即可&#xff0c;但是对于需要处理的接口&#xff0c;如需要转码、替换值等&#xff0c;则就麻烦一些&#xff0c;一般我们都是先手动把修改好的值拷贝到请求里再进行请…

干法制程中的辉光放电

在芯片制程中&#xff0c;几乎所有的干法制程&#xff0c;如PVD&#xff0c;CVD,干法刻蚀等&#xff0c;都逃不过辉光放电现象。辉光放电&#xff0c;是一种在低压下电离气体的过程&#xff0c;它在半导体制程中的许多重要步骤中有着核心作用。那您知道什么是“启辉”吗&#x…

Vue3使用kkFileView预览文件pdf

kkFileView - 在线文件预览kkFileView官网 - kkFileView使用Spring Boot搭建&#xff0c;易上手和部署&#xff0c;基本支持主流办公文档的在线预览&#xff0c;如doc,docx,Excel,pdf,txt,zip,rar,图片等等https://kkfileview.keking.cn/zh-cn/docs/usage.html业务场景&#xf…

【探索Linux】—— 强大的命令行工具 P.17(进程信号 —— 信号保存 | 阻塞信号 | sigprocmask() | sigpending() )

阅读导航 引言一、阻塞信号1. 信号相关常见概念&#xff08;1&#xff09;信号递达&#xff08;2&#xff09;信号未决&#xff08;3&#xff09;阻塞信号&#xff08;4&#xff09;忽略信号 2. 信号在内核中的表示⭕信号在内核中的表示示意图 3. sigset_t &#xff08;数据类型…

viple模拟器使用(三):unity模拟器中实现沿右墙迷宫算法

沿右墙迷宫算法原理 默认直行&#xff1b;右侧有路&#xff0c;则右转&#xff1b;前方无路&#xff0c;则左转。 由于unity模拟器中使用机器人移动动力控制和机器人转动角度控制来实现控制机器人前进、后退、暂停、左转、右转 。 程序编写 主机以及配置 通过内建事件初始化机…

云表|低代码助力职场人,一招制敌解决办公难题

身在职场&#xff0c;我们时常会面临一系列令人头疼的难题&#xff1a; ● 突然被领导要求30分钟内汇总所有人的填报信息&#xff0c;看着面前格式五花八门的Excel表格&#xff0c;我们无所适从&#xff0c;不知从何下手。 ● 在这个数字化的时代&#xff0c;公司仍然沿用古老的…

【数据中台】开源项目(2)-Davinci可视应用平台

1 平台介绍 Davinci 是一个 DVaaS&#xff08;Data Visualization as a Service&#xff09;平台解决方案&#xff0c;面向业务人员/数据工程师/数据分析师/数据科学家&#xff0c;致力于提供一站式数据可视化解决方案。既可作为公有云/私有云独立部署使用&#xff0c;也可作为…

【操作宝典】SQL巨擘:掌握SQL Server Management的终极秘籍!

目录 ⛳️【SQL Server Management】 ⛳️1. 启动登录 ⛳️2. 忘记密码 ⛳️3. 操作数据库和表 3.1 新建数据库text 3.2 新建表 3.3 编辑表 3.4 编写脚本 ⛳️【SQL Server Management】 ⛳️1. 启动登录 需要开启服务 ⛳️2. 忘记密码 登录windows--> 安全性 -->…