一、 CompletableFuture介绍
多线程开发一般使用Runnable,Callable,Thread,FutureTask,ThreadPoolExecutor,但也有不近如意的地方

Thread + Runnable:执行异步任务,没有返回结果。
Thread + Callable + FutureTask:执行一步任务,有返回结果。

获取返回结果,基于get方法获取,线程需要挂起在WaitNode里。
获取返回结果,基于isDone判断任务的状态,但是这里需要不断轮询。

上述的方式都是有一定的局限性的
CompletableFuture是Java 8中引入的一种实现异步编程模型的方式,它是Future的扩展,提供了更强大、更灵活的功能。CompletableFuture可以表示两个异步任务之间的顺序关系或并行关系,同时提供了一些方便的工具方法来组合这些关系。
二、 应用
首先对CompletableFuture提供的函数式编程中三个函数有一个掌握

Supplier 生产者,没有入参,有返回结果
Consumer 消费者,有入参,但是没有返回结果
Function<T,U> 函数,有入参,又有返回结果

2.1 功能
并行执行

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

依赖关系

thenApply():把前面任务的执行结果,交给后面的Function。
thenCompose():用来连接两个有依赖关系的任务,结果由第二个任务返回。

or聚合关系

applyToEither():两个任务哪个执行的快,就使用哪一个结果,有返回值 。
acceptEither():两个任务哪个执行的快,就消费哪一个结果,无返回值 。
runAfterEither():任意一个任务执行完成,进行下一步操作(Runnable类型任务。

and集合关系

thenCombine():合并任务,有返回值 。
thenAccepetBoth():两个任务执行完成后,将结果交给thenAccepetBoth处理,无返回值 。
runAfterBoth():两个任务都执行完成后,执行下一步操作(Runnable类型任务。

结果处理

whenComplete:当任务完成时,将使用结果(或 null)和此阶段的异常(或 null如果没有)执行给定操作。
exceptionally:返回一个新的CompletableFuture,当前面的CompletableFuture完成时,它也完成,当它异常完成时,给定函数的异常触发这个CompletableFuture的完成。

2.2 supplyAsync
CompletableFuture如果不提供线程池的话,默认使用的ForkJoinPool,而ForkJoinPool内部是守护线程,如果main线程结束了,守护线程会跟着一起结束。
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) {
CompletableFuture firstTask = CompletableFuture.supplyAsync(() -> {
System.out.println(“task begin!”);
System.out.println(“task end!”);
return “result”;
});

String result1 = firstTask.join();
String result2 = null;
try {result2 = firstTask.get();
} catch (InterruptedException e) {e.printStackTrace();
} catch (ExecutionException e) {e.printStackTrace();
}System.out.println(result1 + "," + result2);

}

2.3 runAsync
当前方式既不会接收参数,也不会返回任何结果,非常基础的任务编排方式
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) throws IOException {
CompletableFuture.runAsync(() -> {
System.out.println(“task begin!”);
System.out.println(“task end!”);
});

System.in.read();

}

2.4 thenApply,thenApplyAsync
有任务A,还有任务B。任务B需要在任务A执行完毕后再执行。而且任务B需要任务A的返回结果。
任务B自身也有返回结果。thenApply可以拼接异步任务,前置任务处理完之后,将返回结果交给后置任务,然后后置任务再执行thenApply提供了带有Async的方法,可以指定每个任务使用的具体线程池。
thenApply:
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) {
CompletableFuture taskA = CompletableFuture.supplyAsync(() -> {
String id = UUID.randomUUID().toString();
System.out.println(“taskA:” + id);
return id;
});
CompletableFuture taskB = taskA.thenApply(result -> {
System.out.println(“taskA resule:” + result);
result = result.replace(“-”, “”);
return result;
});

    System.out.println("main task deal result:" + taskB.join());
}

thenApplyAsync:
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture taskB = CompletableFuture.supplyAsync(() -> {
String id = UUID.randomUUID().toString();
System.out.println(“taskA:” + id + “,” + Thread.currentThread().getName());
return id;
}).thenApplyAsync(result -> {
System.out.println(“taskB get taskA result:” + result + “,” + Thread.currentThread().getName());
result = result.replace(“-”, “”);
return result;
},executor);

    System.out.println("main thread:" + taskB.join());
}

2.5 thenAccept,thenAcceptAsync(自定义线程池)
套路和thenApply一样,都是任务A和任务B的拼接前置任务需要有返回结果,后置任务会接收前置任务的结果,返回后置任务,没有返回值
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) throws IOException {
CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA”);
return “abcdefg”;
}).thenAccept(result -> {
System.out.println(“taskB,get result:” + result);
});
System.in.read();
}

2.6 thenRun,thenRunAsync(自定义线程池)
套路和thenApply,thenAccept一样,都是任务A和任务B的拼接,前置任务没有返回结果,后置任务不接收前置任务结果,后置任务也没有返回结果。
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) throws IOException {
CompletableFuture.runAsync(() -> {
System.out.println(“taskA begin!”);
}).thenRun(() -> {
System.out.println(“taskB begin!”);
});
System.in.read();
}

2.7 thenCombine,thenAcceptBoth,runAfterBoth
比如有任务A,任务B,任务C。任务A和任务B并行执行,等到任务A和任务B全部执行完毕后,再执行任务C。
2.7.1 thenCombine
当前方式当前方式前置任务需要有返回结果,后置任务接收前置任务的结果,有返回值
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) {
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 10;
}).thenCombine(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 10;
}), (r1, r2) -> {
System.out.println(“taskC begin!!”);
return r1 + r2;
});
System.out.println("taskC result = " + future.join());
}

2.7.2 thenAcceptBoth
当前方式前置任务需要有返回结果,后置任务接收前置任务的结果,没有返回值
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 10;
}).thenAcceptBoth(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 10;
}), (r1, r2) -> {
System.out.println(“taskC begin!!”);
int r = r2 + r1;
System.out.println("taskC result = " + r);
});
}

2.7.3 runAfterBoth
当前方式前置任务不需要有返回结果,后置任务不会接收前置任务的结果,没有返回值
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 10;
}).runAfterBoth(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 10;
}), () -> {
System.out.println(“taskC begin!!”);
});
}

2.8 applyToEither,acceptEither,runAfterEither
这三个方法:比如有任务A,任务B,任务C。任务A和任务B并行执行,只要任务A或者任务B执行完毕,开始执行任务C.
applyToEither:可以接收结果并且返回结果,acceptEither:可以接收结果没有返回结果,runAfterEither:不接收结果也没返回结果,三个方法拼接任务的方式都是一样的,applyToEither:只演示一个其它套路一样。
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) throws IOException {
CompletableFuture taskC = CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 78;
}).applyToEither(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 66;
}), resultFirst -> {
System.out.println(“taskC begin!!”);
return resultFirst;
});
System.out.println(taskC.join());
System.in.read();
}

2.9 exceptionally,thenCompose,handle
exceptionally:
这个也是拼接任务的方式,但是只有前面业务执行时出现异常了,才会执行当前方法来处理.
只有异常出现时,CompletableFuture的编排任务没有处理完时,才会触发。
拿不到任务结果。

whenComplete,handle:
这两个也是异常处理的套路,可以根据方法描述发现,他的功能方向比exceptionally要更加丰富
whenComplete:
可以拿到返回结果同时也可以拿到出现的异常信息,但是whenComplete本身是Consumer不能返回结果。无法帮你捕获异常,但是可以拿到异常返回的结果。
handle:
可以拿到返回结果同时也可以拿到出现的异常信息,并且也可以指定返回托底数据。可以捕获异常的,异常不会抛出去。

java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) throws IOException {
CompletableFuture taskC = CompletableFuture.supplyAsync(() -> {
System.out.println(“taskA begin!!”);
return 78;
}).applyToEither(CompletableFuture.supplyAsync(() -> {
System.out.println(“taskB begin!!”);
return 66;
}), resultFirst -> {
System.out.println(“taskC begin!!”);
return resultFirst;
}).handle((r,ex) -> {
System.out.println(“handle:” + r);
System.out.println(“handle:” + ex);
return -1;
});
/.exceptionally(ex -> {
System.out.println(“exceptionally:” + ex);
return -1;
});
/
/.whenComplete((r,ex) -> {
System.out.println(“whenComplete:” + r);
System.out.println(“whenComplete:” + ex);
});
/
System.out.println(taskC.join());
}

2.10 allOf,anyOf
2.10.1 allOf
allOf的方式是让内部编写多个CompletableFuture的任务,多个任务都执行完后,才会继续执行你后续拼接的任务。
allOf返回的CompletableFuture是Void,没有返回结果
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) throws IOException {
CompletableFuture.allOf(
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskA begin!!”);
}),
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskB begin!!”);
}),
CompletableFuture.runAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskC begin!!”);
})
).thenRun(() -> {
System.out.println(“taskD begin!!”);
});

}

2.10.2 anyOf:
anyOf是基于多个CompletableFuture的任务,只要有一个任务执行完毕就继续执行后续,最先执行完的任务做作为返回结果的入参
java 体验AI代码助手 代码解读复制代码 public static void main(String[] args) throws IOException {
CompletableFuture.anyOf(
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskA begin!!”);
return “A”;
}),
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskB begin!!”);
return “B”;
}),
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“taskC begin!!”);
return “C”;
})
).thenAccept(r -> {
System.out.println(“taskD begin,” + r + “first end”);
});
}

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

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

相关文章

开源 Arkts 鸿蒙应用 开发(六)数据持久--文件和首选项存储

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 Arkts …

【Bluedroid】蓝牙协议栈控制器能力解析与核心功能配置机制(decode_controller_support)

本文围绕Bluedroid蓝牙协议栈中控制器能力解析与核心功能配置的关键代码展开&#xff0c;详细阐述蓝牙协议栈如何通过解析控制器硬件能力&#xff0c;构建 SCO/eSCO、ACL 数据包类型支持掩码&#xff0c;配置链路策略、安全服务、查询与扫描模式等核心功能。这些机制确保协议栈…

小架构step系列07:查找日志配置文件

1 概述 日志这里采用logback&#xff0c;其为springboot默认的日志工具。其整体已经被springboot封装得比较好了&#xff0c;扔个配置文件到classpath里就能够使用。 但在实际使用中&#xff0c;日志配置文件有可能需要进行改动&#xff0c;比如日志的打印级别&#xff0c;平…

一文讲清楚React Hooks

文章目录一文讲清楚React Hooks一、什么是 React Hooks&#xff1f;二、常用基础 Hooks2.1 useState&#xff1a;状态管理基本用法特点2.2 useEffect&#xff1a;副作用处理基本用法依赖数组说明2.3 useContext&#xff1a;上下文共享基本用法特点三、其他常用 Hooks3.1 useRed…

Apache http 强制 https

1. 修改一下文件配置 sudo nano /etc/apache2/sites-enabled/000-default.conf<VirtualHost *:80>ServerName hongweizhu.comServerAlias www.hongweizhu.comServerAdmin webmasterlocalhostDocumentRoot /var/www/html# 强制重定向到HTTPSRewriteEngine OnRewriteCond …

【读代码】GLM-4.1V-Thinking:开源多模态推理模型的创新实践

一、基本介绍 1.1 项目背景 GLM-4.1V-Thinking是清华大学KEG实验室推出的新一代开源视觉语言模型,基于GLM-4-9B-0414基础模型构建。该项目通过引入"思维范式"和强化学习课程采样(RLCS)技术,显著提升了模型在复杂任务中的推理能力。其创新点包括: 64k超长上下文…

从代码生成到智能运维的革命性变革

AI大模型重塑软件开发&#xff1a;从代码生成到智能运维的革命性变革 希望对大家有一定的帮助&#xff0c;进行参考 目录AI大模型重塑软件开发&#xff1a;从代码生成到智能运维的革命性变革 希望对大家有一定的帮助&#xff0c;进行参考一、范式转移&#xff1a;软件开发进入&…

豆包编写Java程序小试

今天下载了一本第四版电气工程师手册&#xff0c;非常棒的一本书&#xff0c;在给PDF添加目录的时候&#xff0c;由于目录有将近60页&#xff0c;使用老马开发的PdgCntEditor有点卡顿&#xff0c;不过补充下&#xff0c;老马这个PdgCntEditor还是非常好的。所以我决定用Java编一…

SpringBoot整合腾讯云新一代行为验证码

一 产品介绍 腾讯云官方介绍链接 腾讯云新一代行为验证码&#xff08;Captcha&#xff09;&#xff0c;基于十道安全防护策略&#xff0c;为网页、App、小程序开发者打造立体、全面的人机验证。在保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时&…

SenseGlove新一代外骨骼力反馈手套Rembrand来袭!亚毫米级手部动捕+指尖触觉力采集+5Dof主动力反馈多模态

在远程机器人操作领域&#xff0c;精准的触觉感知与灵活的动作控制始终是核心需求。SenseGlove 新推出的 Rembrandt 力反馈外骨骼数据手套&#xff0c;以先进技术为支撑&#xff0c;为远程操控人形机器人手部提供了无缝解决方案&#xff0c;让操作更精准、更高效。值得一提的是…

Linux 信号机制:操作系统的“紧急电话”系统

想象一下&#xff0c;你正在电脑前专心工作&#xff0c;突然手机响了——这是一个通知&#xff0c;要求你立即处理一件新事情&#xff08;比如接电话&#xff09;。 Linux 系统中的信号&#xff08;Signal&#xff09;​​ 机制&#xff0c;本质上就是操作系统内核或进程之间用…

论文略读:Prefix-Tuning: Optimizing Continuous Prompts for Generation

2021 ACL固定预训练LM&#xff0c;为LM添加可训练&#xff0c;任务特定的前缀这样就可以为不同任务保存不同的前缀这种前缀可以看成连续可微的soft prompt&#xff0c;相比于离散的token&#xff0c;更好优化&#xff0c;效果更好训练的时候只需要更新prefix部分的参数&#xf…

CSS基础选择器、文本属性、引入方式及Chorme调试工具

CSS基础 1.1 CSS简介 CSS 是层叠样式表 ( Cascading Style Sheets ) 的简称. 有时我们也会称之为 CSS 样式表或级联样式表。 CSS 是也是一种标记语言 CSS 主要用于设置 HTML 页面中的文本内容&#xff08;字体、大小、对齐方式等&#xff09;、图片的外形&#xff08;宽高、边…

RabbitMQ 高级特性之事务

1. 简介与 MySQL、Redis 一样&#xff0c;RabbitMQ 也支持事务。事务中的消息&#xff0c;要么全都发送成功&#xff0c;要么全部发送失败&#xff0c;不会出现一部分成功一部分失败的情况。2. 使用事务发送消息spring 中使用 RabbitMQ 开启事务需要两步&#xff1a;第一步&…

iframe 的同源限制与反爬机制的冲突

一、事件背景A域名接入了动态防护&#xff08;Bot 防护、反爬虫机制&#xff09;&#xff0c;同时第三方业务B域名通过内嵌iframe的方式调用了A域名下的一个链接。二、动态防护介绍&#xff1a;动态防护&#xff08;也称为 Bot 防护、反爬虫机制&#xff09;是网站为了防止自动…

Rust 的 Copy 语义:深入浅出指南

在 Rust 中&#xff0c;Copy 是一个关键的特性&#xff0c;它定义了类型的复制行为。理解 Copy 语义对于掌握 Rust 的所有权系统和编写高效代码至关重要。一、核心概念&#xff1a;Copy vs Move特性Copy 类型非 Copy 类型 (Move)赋值行为按位复制 (bitwise copy)所有权转移 (ow…

Qt的信号与槽(二)

Qt的信号与槽&#xff08;二&#xff09;1.自定义槽2.通过图形化界面来生成自定义槽3.自定义信号3.信号和槽带参数4.参数数量5.connect函数的设计&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f680;系列专栏&#xf…

Java研学-MongoDB(三)

三 文档相关 7 文档统计查询① 语法&#xff1a; // 精确统计文档数 慢 准 dahuang> db.xiaohuang.countDocuments({条件}) 4 // 粗略统计文档数 快 大致准 dahuang> db.xiaohuang.estimatedDocumentCount({条件}) 4② 例子&#xff1a; // 精确统计文档数 name为奔波儿灞…

TCP协议格式与连接释放

TCP报文段格式 TCP虽然是面向字节流的&#xff0c;但TCP传送带数据单元确是报文段。TCP报文段分为首部和数据段部分&#xff0c;而TCP的全部功能体现在它在首部中各字段的作用。因此&#xff0c;只有弄清TCP首部各字段的作用才能掌握TCP的工作原理。 TCP报文段首部的前20字节是…

CSS05:结构伪类选择器和属性选择器

结构伪类选择器 /*ul的第一个子元素*/ ul li:first-child{background: #0af6f6; }/*ul的最后一个子元素*/ ul li:last-child{background: #d27bf3; } /*选中p1&#xff1a;定位到父元素&#xff0c;选择当前的第一个元素 选择当前p元素的父级元素&#xff0c;选中父级元素的第…