【多线程开发 3】从源码到实践CompletableFuture

news2024/11/16 21:30:30

【多线程开发 3】从源码到实践CompletableFuture

2024年5月22日

本文将从以下几个点讲解CompletableFuture:

  • 前身

  • 是什么?

  • 可以用来做什么?

  • 源码原理

  • 实战

  • 其他包装类

前身

CompletableFuture的依赖如图所示:
在这里插入图片描述

在这里插入图片描述

所以我打算从Runnable、Future、RunnableFuture、FutureTask讲起

Runnable

Runnable就是一个带着执行方法的接口,通过实现Runnable可以实现开始一个线程执行对应的无返回值的操作。

Future

Future保存异步计算的结果,可以在我们执行任务时去做其他工作,体现了解耦的思想。Future 可以对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

其实本质上就是对Runnable或者Callable任务做了一层异步方法封装

RunnableFuture

RunnableFuture实际上只是Runnable接口和Future接口的总和,使用较少。

FutureTask

FutureTask是Future接口的一个唯一实现类。

FutureTask可以对Task做一个异步执行,通过FutureTask的构造函数可以将你想进行异步操作的Task封装进去。FutureTask是个适配器类,作为一个转换器,将Runnable和Callable适配,适配器类是适配器模式的核心,它通过实现RunnableFuture和组合Callable使得两者产生关系。

CompletableFuture可以做什么?

如果只使用Future类可以进行简单的异步执行,但是使用Future的get方法会导致主进程阻塞,并且也无法做到多个异步任务之间的依赖关系,并且有时候异步任务报错不会输出堆栈,Future任务也不会触发后续操作,没有提供函数式编程,不过以上CompletableFuture都可以帮助我们实现。

实战

以下是一些常用API,需要注意的是CompletableFuture可以使用默认线程池或者是自定义线程池,默认线程池是ForkJoinPool

    @Test
    public void test1() throws ExecutionException, InterruptedException, java.util.concurrent.ExecutionException {
        CompletableFuture<String> base = new CompletableFuture<>();
        CompletableFuture<String> future = base.thenApply(s -> s + " 2").thenApply(s -> s + " 3");
        base.complete("1");
        System.out.println(future.get());
    }


    @Test
    public void test2() throws ExecutionException, InterruptedException, java.util.concurrent.ExecutionException {
        CompletableFuture<String> base = new CompletableFuture<>();
        CompletableFuture<String> future = base.thenApply(s -> s + " 2").thenApply(s -> s + " 3");
        future.complete("1");
        System.out.println(future.get());
    }


    @Test
    public void test3() throws java.util.concurrent.ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        CompletableFuture<String> step1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行【步骤1】");
            return "【步骤1的执行结果】";
        }, executor);
        CompletableFuture<String> step2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行【步骤2】");
            return "【步骤2的执行结果】";
        }, executor);
        CompletableFuture<String> step3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行【步骤3】");
            return "【步骤3的执行结果】";
        }, executor);

        CompletableFuture<Object> stepN = CompletableFuture.anyOf(step1, step2, step3);
        System.out.println("步骤N的结果:" + stepN.get());

        executor.shutdown();
    }

    @Test
    public void test4() throws java.util.concurrent.ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        CompletableFuture<String> step1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行【步骤1】");
            return "【步骤1的执行结果】";
        }, executor);
        CompletableFuture<String> step2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行【步骤2】");
            return "【步骤2的执行结果】";
        }, executor);
        CompletableFuture<String> step3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行【步骤3】");
            return "【步骤3的执行结果】";
        }, executor);

        CompletableFuture<Void> stepN = CompletableFuture.allOf(step1, step2, step3);
        System.out.println("步骤N的结果:" + stepN.get());

        executor.shutdown();
    }

    @Test
    public void test5() throws java.util.concurrent.ExecutionException, InterruptedException {

        // 生产者,可以指定返回结果
        CompletableFuture<String> firstTask = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步任务开始执行");
            System.out.println("异步任务执行结束");
            return "返回结果";
        });

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


    @Test
    public void test6() throws IOException {
        CompletableFuture.supplyAsync(() -> {
            System.out.println("任务A");
            return "abcdefg";
        }).thenAccept(result -> {
            System.out.println("任务b,拿到结果处理:" + result);
        });

        System.in.read();

    }

    @Test
    public void test7() throws IOException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务A执行");
            return 10;
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            System.out.println("任务B执行");
            return 10;
        }), (r1, r2) -> {
            System.out.println("任务C执行");
            return r1 + r2;
        });
        System.out.println("任务C结果=" + future.join());
    }

其他包装类

其他也有一些API可以实现异步编程,常用的有以下几个,后续有时间的话可以单独写文章解析

  • Spring注解@Async
  • 消息队列
  • 第三方异步框架,比如Hutool的ThreadUtil
  • Guava异步

这几个是进行开发的时候常用的

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

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

相关文章

二叉树的顺序结构及实现(堆的实现)

一.二叉树的顺序结构&#xff1a; 普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆 ( 一种二叉树 ) 使用顺序结构的数组来存储&#xff0c;需要注意的是这里的堆和操作系统 虚拟进程地址…

C++入门3——类与对象2(类的6个默认成员函数)

目录 1.类的6个默认成员函数 2. 构造函数 2.1 构造函数的概念 2.2 构造函数的特性 3. 析构函数 3.1 析构函数的概念 3.2 析构函数的特性 4.拷贝构造函数 4.1 拷贝构造函数的概念 4.2 拷贝构造函数的特性 5.赋值运算符重载函数 5.1运算符重载函数 5.2 赋值运算符重…

探索文档解析技术,推动大模型训练与应用

探索文档解析技术&#xff0c;推动大模型训练与应用 0. 前言1. CCIG 20241.1 会议简介1.2 大模型技术及其前沿应用论坛1.3 走进合合信息 2. 大模型时代2.1 大模型的发展与应用2.2 大模型面临的挑战 3. 文档解析技术3.1 文档解析技术难点3.2 TextIn 文档解析算法流程 4. 大模型时…

UE5 Http Server

前言 最近要用UE 作为一个服务器去接收来自外部的请求&#xff0c;从而在UE中处理一些内容&#xff0c;但是之前只做过请求&#xff0c;哪整过这玩意&#xff0c;短期内还得出结果&#xff0c;那怎么搞嘞&#xff0c;本着省事的原则就找找呗&#xff0c;有没有现成的&#xff0…

【基础算法总结】位运算

位运算 1.基础位运算2.常见用法总结3.面试题 01.01. 判定字符是否唯一4.丢失的数字5.两整数之和6.只出现一次的数字 II7.面试题 17.19. 消失的两个数字 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励…

CCIG 2024:合合信息文档解析技术突破与应用前景

目录 背景当前大模型训练和应用面临的问题训练Token耗尽训练语料质量要求高LLM文档问答应用中文档解析不精准 合合信息的文档解析技术1. 具备多文档元素识别能力2. 具备版面分析能力3. 高性能的文档解析4. 高精准、高效率的文档解析文档多板式部分示例 文档解析典型技术难点元素…

Go Modules 使用

文章参考https://blog.csdn.net/wohu1104/article/details/110505489 不使用Go Modules&#xff0c;所有的依赖包都是存放在 GOPATH /pkg下&#xff0c;没有版本控制。如果 package 没有做到完全的向前兼容&#xff0c;会导致多个项目无法运行(包版本需求不同)。 于是推出了g…

JVM学习-类加载过程(一)

概述 在Java中数据类型分为基本数据类型和引用数据类型&#xff0c;基本数据类型由虚拟机预先定义&#xff0c;引用数据类型则需要进行类的加载按Java虚拟机规范&#xff0c;从class文件加载到内存中的类&#xff0c;到类卸载出内存为止&#xff0c;它的整个生命周期包含以下7…

Java 异常处理中try-catch块、finally子句以及自定义异常的使用

Java 异常处理是 Java 语言中非常重要的一部分&#xff0c;用来处理程序运行过程中可能发生的各种异常情况&#xff0c;确保程序的稳定性和可靠性。 一、Java 异常处理概述 异常是程序运行过程中出现的非正常情况。Java 使用异常类&#xff08;Exception 类及其子类&#xff…

建WordPress主题官网模板

蓝色的中文WordPress企业模板 https://www.zhanyes.com/qiye/6305.html 暗红色WordPress律师事务所网站模板 https://www.zhanyes.com/qiye/23.html 红色大banner图WordPress外贸网站模板 https://www.zhanyes.com/waimao/27.html

【C语言】探索文件读写函数的全貌

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 &#x1f525;引言 本章将介绍文件读取函数的相关知识和展示使用场景&am…

AI自动化办公:批量将Excel表格英文内容翻译为中文

有一个50列的表格&#xff0c;里面都是英文&#xff0c;要翻译成中文&#xff1a; 在ChatGPT中输入提示词&#xff1a; 你是一个开发AI大模型应用的Python编程专家&#xff0c;要完成以下任务的Python脚本&#xff1a; 打开Excel文件&#xff1a;"F:\AI自媒体内容\AI行业…

harbor -- docker私有仓库安装配置

1 安装docker-compose $ curl -L "https://get.daocloud.io/docker/compose/releases/download/v1.25.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose $ chmod x /usr/local/bin/docker-compose 2 安装配置harbor $ wget https://g…

JS-51-Node.js10-yarn

一、yarn的简介 Yarn 是一款 JavaScript 的包管理工具&#xff08;npm的代替方案&#xff09;&#xff0c;是 Facebook, Google, Exponent 和 Tilde 开发的一款新的 JavaScript 包管理工具。 正如 Yarn 官网的介绍&#xff0c;Yarn 的具有速度快 、安全 、可靠 的优点&#x…

嘉立创使用gif

新建原理图 边框设置2 新建pcb图 放置焊盘 排列焊盘 新建符号 封号向导 新建封装 封装向导 符号与封装联结 原件查找 drc设计规则&#xff08;线之间的距离等 布线冲突 顶底层切换 T ,B 顶底连线&#xff0c;自动创造过孔 铺铜 泪滴 网格大小 吸附 元件库

民国漫画杂志《时代漫画》第33期.PDF

时代漫画33.PDF: https://url03.ctfile.com/f/1779803-1248635648-d8235b?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps: 资源来源网络!

任何图≌自己这一几何最起码常识推翻直线公理让R外标准实数一下子浮出水面

黄小宁 h定理&#xff1a;点集AB≌B的必要条件是A≌B。 证&#xff1a;若AB则A必可恒等变换地变为BA≌A&#xff0c;而恒等变换是保距变换。证毕。 如图所示R轴即x轴各元点x沿x轴正向不保距平移变为点y2x就使x轴沿本身拉伸&#xff08;放大&#xff09;变换为y2x轴不≌x轴&…

PDF盖骑缝章

在PDF文件上加盖骑缝章&#xff0c;您可以采取以下几种方法之一&#xff1a; 使用Adobe Acrobat&#xff1a; 打开Adobe Acrobat软件&#xff0c;加载PDF文件。在工具栏选择“工具”选项&#xff0c;找到“骑缝章”或“印章”工具。选择或上传您的骑缝章图片&#xff0c;将其放…

区块链技术:金融行业的信任基石

一、引言 在数字化转型的浪潮中,区块链技术以其独特的优势,正逐渐成为金融行业的信任基石。本文将深入探讨区块链技术在金融行业的应用,通过具体案例的细化和完善,分析其特点和影响。 二、区块链技术的核心特点 1. 去中心化:区块链技术通过分布式账本,实现去中心化的数…

乡村振兴,教育先行:加强农村教育事业发展,提高农民素质,培育新时代新型农民,为美丽乡村建设提供人才保障

目录 一、引言 二、农村教育事业发展的重要性 1、提高农民素质&#xff0c;促进全面发展 2、推动农村经济社会发展 3、传承乡村文化&#xff0c;促进文化振兴 三、加强农村教育事业发展的策略 1、加大教育投入&#xff0c;改善教育设施 2、普及义务教育&#xff0c;提高…