线程 CompletableFuture详解

CompletableFuture用法详解 小笔记 阅读详情

CompletableFuture

参考:https://blog.youkuaiyun.com/u012129558/article/details/78962759
https://www.jianshu.com/p/bdc6bd50f7d2

Future模式的缺点
  • Future虽然可以实现获取异步执行结果的需求,但是它没有提供通知的机制,我们无法得知Future什么时候完成。
  • 要么使用阻塞,在future.get()的地方等待future返回的结果,这时又变成同步操作。要么使用isDone()轮询地判断Future是否完成,这样会耗费CPU的资源。
CompletableFuture介绍

Java 8新增的CompletableFuture类正是吸收了所有Google Guava中ListenableFuture和SettableFuture的特征,还提供了其它强大的功能,让Java拥有了完整的非阻塞编程模型:Future、Promise 和 Callback(在Java8之前,只有无Callback 的Future)。

CompletableFuture弥补了Future模式的缺点。在异步的任务完成后,需要用其结果继续操作时,无需等待。可以直接通过thenAccept、thenApply、thenCompose等方式将前面异步处理的结果交给另外一个异步事件处理线程来处理。

1.创建对象

CompletableFuture有两类最基本的创建对象的静态方法:

CompletableFuture的静态工厂方法
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
public static CompletableFuture<Void> runAsync(Runnable runnable);
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);

runAsync 和 supplyAsync 方法的区别是runAsync返回的CompletableFuture是没有返回值的。

		CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName()+"hello!");
        });

        try {
            Void aVoid = future.get();
            System.out.println(aVoid); //null
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
ForkJoinPool.commonPool-worker-1hello!
null
        ExecutorService executor = Executors.newFixedThreadPool(3);

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "world!",executor);

        try {
            System.out.println(future.get()); //world!
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }


2.获取对象内容

CompletableFuture有几个相关方法,包括:

public T get() throws InterruptedException, ExecutionException;
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
public T join();
public T getNow(T valueIfAbsent);
  • get 方法会使当前线程阻塞,并且等待直到 future 完成,并且将返回 future 的值
  • 带参数的 get 方法需要传入对应的时间长度,一旦超出这个时间,会抛出TimeoutException
  • join 方法与 get 并无太大差别,但 join 方法不能被打断
  • getNow 方法不会阻塞线程,而是立即返回值,如果该 future 当前没有完成,则会立刻返回该方法的传入参数.
  • get 和 join 方法会在正常的情况下返回值,在遇到异常的情况下将异常抛出

说明:通常情况下,为了使所有的多线程都执行完后,再进行下一步处理(如return等),可以使用join。虽然join可以获取结果,但这里是为了使用其阻塞的作用。

1.不阻塞将不会等待结果
		ExecutorService executor = Executors.newFixedThreadPool(3);
        List<String> list = Lists.newArrayList("hi","didi","hello");
        List<String> nList = Lists.newArrayList();
        list.forEach(s->CompletableFuture.runAsync(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            nList.add(s.toUpperCase());
        }, executor));

        System.out.println(nList);//[]

上述由于异步处理时需要花费1s时间,故nList为空。可以等待1s以后,再查看nList的内容:

        ExecutorService executor = Executors.newFixedThreadPool(3);
        List<String> list = Lists.newArrayList("hi","didi","hello");
        List<String> nList = Lists.newArrayList();
        list.forEach(s->CompletableFuture.runAsync(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            nList.add(s.toUpperCase());
        }, executor));

        try {
            Thread.sleep(1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(nList);//[HI, DIDI, HELLO]

上述等待一定时间后,nList可能已经有了全部结果,可能结果不是很全。通过等待时间不是好的做法,我们可以通过join来等待多线程运行结束。

2.join等待多线程运行结束
        ExecutorService executor = Executors.newFixedThreadPool(3);
        List<String> list = Lists.newArrayList("hi","didi","hello");
        List<String> nList = Lists.newArrayList();
        list.forEach(s->CompletableFuture.runAsync(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            nList.add(s.toUpperCase());
        }, executor).join());

        System.out.println(nList);//[HI, DIDI, HELLO]

join将等待所有线程执行完后,执行下一步。

thread1        thread2           thread3
      \            |            /
			    	join(都有结果了往下走)
Java线程池监控及CompletableFuture详解 Java线程池监控及最佳实践。Springboot整合线程池。线程池为多线程创建的开销问题以及线程管理提供了解决方案。通过多任务下线程的重用,即线程池中的线程执行完一个任务后并不立即销毁,而是可以继续执行其它任务。将线程创建的开销摊薄到了多任务上,便能获得高并发环境下系统性能上的提升。 阅读详情

相关推荐

MIT Bevfusion环境安装 Docker方式,nuscenes数据处理

Bevfusion环境安装,数据生成报错解决module 'numpy' has no attribute 'long';most likely due to a circular import。bevfusion docker环境

Jack_Man_N的博客 1143

Java CompletableFuture:allOf等待所有异步线程任务结束(4)

CompletableFuture:allOf等待所有线程任务结束(4) private void method() throws ExecutionException, InterruptedException { CompletableFuture&lt;String&gt; f1 = CompletableFuture.supplyAsync(() -&gt; { ...

Zhang Phil 7万+

华中科技大学 计算机组成原理 educoder Logisim平台 计算机数据表示实验

本文主要是对 计算机数据表示实验的笔记和相关Logisim平台的图,供大家学习交流使用。 需要源文件或者源代码,可以留言评论! 目录实验目的第1关:汉字国标码转区位码实验第2关:汉字机内码获取实验第3关:偶校验编码设计第4关:偶校验解码电路设计第5关:16位海明编码电路设计第6关:16位海明解码电路设计第7关:海明编码流水传输实验第8关:16位CRC并行编解码电路设计第9关:CRC编码流水传输实验实验结果: 实验目的 本实训将帮助同学们巩固对计算机中数据表示方法的理解,要求能设计汉字国标码与区位码之间的转换

weixin_48383580的博客 2万+

异步执行由于主线程提前结束导致异步线程提前终止

springboot异步任务由于主线程结束而提前终止

qq_42055104的博客 2310

硬件开发实践:高速 PCB 差分信号与时钟同步优化

由两条互补信号线组成(正负极)接收端只关注两线之间电压差共模噪声对两线同时作用,可被抵消。

2501_93174775的博客 392

汇川机器人与PLC通信-ModbusTCP超详细案例

通过汇川机器人与PLC的ModbusTCP通信项目案例,我们可以了解通讯配置的过程,地址映射的方式,对接信号的转换,运行时序的逻辑等注意事项,帮助我们快速应用到项目中。

weixin_44166380的博客 1万+

线程中方法睡眠对执行线程的影响

异步编排中线程中方法是否睡眠对执行线程

qq_50907269的博客 612

从DDH到FastANI:原核生物分类黄金标准的进化史与技术对比

本文系统梳理了原核生物分类标准从DDH到FastANI的四次技术革命,详细解析了95%相似度阈值的科学依据及应用场景。通过对比DDH、16S rRNA、ANI和FastANI的技术特点与性能指标,为微生物研究者提供基因组分类的实战指南,并展望第三代测序时代的分类新挑战。

weixin_29275257的博客 412

CompletableFuture等待所有任务结束

CompletableFuture.supplyAsync() 带有返回值的异步处理,调用get()阻塞直到具有返回值; 当对多个CompletableFuture进行等待处理时,CompletableFuture提供了 allOf(completableFutures).join() 进行处理;具体使用如下: List<List<ExportInfo>> rs = CollUtil.split(res, 200000); CompletableFuture[] co

baidu_34762389的博客 9832

Agentic RAG:RAG从静态到具有理解、推理、决策的Agentic RAG

RAG技术演进:从静态检索到智能代理 RAG(检索增强生成)技术经历了五个关键发展阶段:基础RAG(关键词检索)、高级RAG(语义理解)、模块化RAG(灵活架构)、图RAG(知识图谱)和最新的Agentic RAG(智能代理)。Agentic RAG通过引入自主AI代理,具备反思、规划、工具使用和多代理协作能力,实现了动态决策和自适应工作流。相比传统RAG的静态检索流程,Agentic RAG能处理复杂多步推理任务,通过自我改进机制提高输出质量,并支持多专业代理协作,显著提升了RAG系统在复杂场景下的表现。

2532

SAP 系统间 SSO 的真正价值,从 SM59 到可信 RFC 的安全设计

SAP S/4HANA系统间Single Sign-On(SSO)的核心价值在于集中管理通信身份与信任关系,而非仅减少密码输入。传统固定账号密码方式在系统规模扩大后会面临密码管理、审计追踪等挑战。通过SM59配置可信RFC目标系统,结合SSL证书或SAP Trusted System等强认证机制,能有效降低安全凭据暴露风险。SSO配置需配合授权对象、角色管理等建立清晰的信任边界,实现系统间安全通信的同时保持可审计性。这种方案特别适用于Fiori前端与S/4HANA后端等场景,通过可信RFC传递用户身份,避免

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1060

Java的所有线程知识精华全在CompletableFuture了

java8中的CompletableFuture串联了java中的所有java线程知识

我是香菜 9499

基于Simulink和Control System Toolbox的线控转向(Steer-by-Wire)系统设计

通过上述步骤,我们成功设计并实现了基于 Simulink 和 Control System Toolbox 的线控转向(Steer-by-Wire)系统。该系统能够接收来自方向盘的角度指令,经过控制器处理后,驱动转向执行器(如电动机),实现对车辆前轮转向角度的精确控制。通过虚拟场景仿真、硬件在环测试和实车测试,验证了系统的响应速度、控制精度、车辆稳定性和实时性能,并通过参数优化进一步提升了系统的性能。

MHD0815的博客 549

ThreadPoolExecutor线程池与CompletableFuture线程异步编排

ThreadPoolExecutor线程池与CompletableFuture线程异步编排

zyxzyx666的博客 2303

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

异步线程的复习以及CompletableFuture线程池的使用详解

1.初始化线程的四种方式 继承Thread类 实现Runnable接口 实现Callable接口+FutureTask(可以拿到返回结果,可以处理异常) 创建线程池 方式1和方式2:主进程无法获取线程的运算结果,不适合分布式的场景 方式3:主进程可以获取线程的运算结果,但是不利于控制服务器的线程资源。可能会导致服务器线程资源耗尽。 方式4: 通过初始化线程池可以保证线程的稳定,也可以获取到结果,并捕获异常,但是,在业务复杂的情况下,一个异步调用可能会依赖于另一个异步调用的执行结果 2.具体实现方式

weixin_44961111的博客 617

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

CompletableFuture异步和线程池

CompletableFuture异步和线程池讲解

weixin_44674424的博客 5561

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

多线程之CompletableFuture全方面解析

多线程之CompletableFuture全方面解析

洱涷zZ的博客 6808

CompletableFuture线程池使用

CompletableFuture 是 Java 8 引入的异步编程工具,其线程管理依赖线程池。使用默认线程池(ForkJoinPool.commonPool())和自定义 ThreadPoolExecutor 存在显著差异

不要让任何事情成为你不去学习的理由。 1007

线程基础和CompletableFuture异步编排

程基础和CompletableFuture异步编排

m0_62946761的博客 2571

线程池、CompletableFuture

1. 线程池 1.1 线程池创建 1.2 核心线程池的内部实现 (1) 内部实现 public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,

m0_38140207的博客 904

CompletableFuture高并发和线程池使用

java高并发,多线程

s07aser123的专栏 3659

如何解决 CompletableFuture 线程死锁

线程死锁的关键在于理解其异步执行机制和线程池的使用方式。:线程池大小不足时,所有线程可能被阻塞在等待操作上,导致后续任务无法执行。可能因任务过多导致线程耗尽,尤其是任务内部有阻塞操作时。),会导致线程被占用,无法执行后续任务,从而引发死锁。互相依赖对方的完成结果,形成死锁。:无限期等待可能导致死锁无法恢复。)中使用阻塞操作(如。

qq_33240556的博客 1364

【Java篇】 1.CompletableFuture使用线程池进行异步多线程处理

多线程编程是提升程序性能和响应速度的关键手段之一, Java 提供了多种方式来实现并发处理,从早期的Thread类到后来的Executor框架,Java 8 引入了,结合线程池(ThreadPool)使用,不仅简化了多线程的编写,还大大提高了代码的可读性和可维护性。相比传统的多线程方式,ThreadPool的组合为开发者提供了更高层次的抽象,保留了灵活性,又降低了复杂性。

yanqingyu000的博客 5890

单线程、Callable、CompletableFuture性能比较,推荐使用CompletableFuture

在多线程合并返回结果时可以用到Callble,它和Runnable的作用差不多,Callabe可以返回结果。先面对单线程、callable、FutureTask的增强版CompletableFuture进行性能比较。 public static void main(String[] args) throws ExecutionException, InterruptedException { //单线程计算累加 Instant start = Instant.now();

qq_22744093的博客 1790

线程池——futuretask、CompletionService、CompletableFuture

java

m0_46598535的博客 3088

CompletableFuture开启异步线程

CompletableFuture异步线程

weixin_44433826的博客 1502
上一篇: 线程7:Callable、Future与线程池使用池
下一篇: shell之awk
王小禾
博客等级 码龄11年 80粉丝 291原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值