线程池与CompletableFuture 异步编排

news2024/9/23 17:21:09

使用线程池的好处:
1、降低资源的消耗
通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗
2、提高响应速度
因为线程池中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务
的状态,当任务来时无需创建新的线程就能执行
3、提高线程的可管理性
线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来
的系统开销。无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,使
用线程池进行统一分配

以下代码首先创建线程池executor ,将其传入异步编排对象CompletableFuture,它提供了四个静态方法来创建一个异步操作。

1、创建异步对象方法

在这里插入图片描述

1、runXxxx 都是没有返回结果的,supplyXxx 都是可以获取返回结果的
2、可以传入自定义的线程池,否则就用默认的线程池
public class Thread1Test {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("方法开始。。。");

        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println(i);
        }, executor);
        System.out.println("方法结束");

    }
}

在这里插入图片描述

2、计算完成时回调方法

使用supplyAsync可以获得线程运行返回结果:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果"+i);
            return i;
        }, executor);
        Integer integer = future.get();

提供了计算完成时回调方法,在处理完成后,对结果进行操作:
在这里插入图片描述
whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。
whenComplete 和 whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池
来进行执行。
方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其他线程
执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
whenComplete可以得到任务完成结果,参数1是结果,参数2是异常:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果"+i);
            return i;
        }, executor).whenComplete((res,excption)->{
            System.out.println("异步完成,结果是"+res+"异常是:"+excption);
        });

这里制造除数为0的异常:
在这里插入图片描述
exceptionally虽然能得到异常信息,但是没法修改返回数据,感知异常,返回默认值

 CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果"+i);
            return i;
        }, executor).whenComplete((res,excption)->{
            System.out.println("异步完成,结果是"+res+"异常是:"+excption);
        }).exceptionally(throwable -> {
            //感知异常,返回默认值
            return 10;
        });
        Integer integer = future.get();

在这里插入图片描述

3、handle方法

在这里插入图片描述
handle和 complete 一样,可对结果做最后的处理(可处理异常),可改变返回值。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println(i);
            return i;
        }, executor).handle((res,thr)->{
            if (res!=null){
                return res *2;
            }
            if (thr!=null){
                return 0;
            }
            return 1;
        });

在这里插入图片描述

4、线程串行化方法

在这里插入图片描述
thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前
任务的返回值。
thenAccept 方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。
thenRun 方法:只要上面的任务执行完成,就开始执行 thenRun,只是处理完任务后,执行
thenRun 的后续操作
带有 Async 是多开一个线程,是异步执行的。同之前。
以上都要前置任务成功完成。

      //线程串行化
        /* 1、 thenRunAsync 不能获取上一步的执行结果
           2、 thenAcceptAsync 能接受上一步结果,但无返回值
           3、 thenApplyAsync能接受上一步结果,有返回值
        * */
 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果"+i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了" + res);

            return "hello" + res;
        }, executor);

在这里插入图片描述

5、两任务组合 - 都要完成

在这里插入图片描述
两个任务必须都完成,触发该任务。

runAfterBoth:组合两个 future,不需要获取 future 的结果,只需两个 future 处理完任务后,
处理该任务。

CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任务1线程结束"+i);
            return i;
        }, executor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程" + Thread.currentThread().getId());

            System.out.println("任务2线程结束");
            return "hello";
        }, executor);
        future01.runAfterBothAsync(future02,()->{
            System.out.println("任务3开始");
        },executor);

        System.out.println("方法结束");

在这里插入图片描述
thenAcceptBoth:组合两个 future,获取两个 future 任务的返回结果,然后处理任务,没有
返回值。

future01.thenAcceptBothAsync(future02,(f1,f2)->{
           System.out.println("任务3开始...之前的结果"+f1+f2);
       },executor);

在这里插入图片描述

thenCombine:组合两个 future,获取两个 future 的返回结果,并返回当前任务的返回值

 CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return "组合处理任务1、2的结果" + f1 + f2 + "999";
        }, executor);

在这里插入图片描述

6、两任务组合 - 一个完成

在这里插入图片描述

runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返
回值。

 future01.runAfterEitherAsync(future02,()->{
           System.out.println("任务3开始前的结果");
       },executor);

在这里插入图片描述
acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。

future01.acceptEitherAsync(future02,(res)->{
            System.out.println("任务3开始前的结果"+res);
        },executor);

在这里插入图片描述
applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。

CompletableFuture<String> eitherAsync = future01.applyToEitherAsync(future02, (res) -> {
            System.out.println("任务3开始前结果" + res);
            return res.toString() + "--->" + "ke";
        }, executor);

        System.out.println("方法结束"+eitherAsync.get());

在这里插入图片描述

7、多任务组合

在这里插入图片描述

allOf:等待所有任务完成

  CompletableFuture<String> img = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品信息");
            return "hello.jpg";
        },executor);
        CompletableFuture<String> attr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询属性信息");
            return "黑丝";
        },executor);
        CompletableFuture<String> desc = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("查询商品介绍");

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "油量";
        },executor);
        CompletableFuture<Void> allOf = CompletableFuture.allOf(img, attr, desc);
        allOf.get();
        System.out.println("任务结束"+img.get()+attr.get()+desc.get());

在这里插入图片描述
anyOf:只要有一个任务完成

 CompletableFuture<Object> anyOf = CompletableFuture.anyOf(img, attr, desc);

在这里插入图片描述

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

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

相关文章

STM32启动详细流程分析(一)

问题提出 大家不妨设想一下&#xff0c;cpu 的工作是什么&#xff0c;cpu 是没有主观意识的&#xff0c;它只会按照特定的指令执行相应的操作&#xff0c;用专业术语来说就是&#xff1a;取指 -> 译码 -> 执行&#xff0c;译码和执行肯定是在 cpu 内部进行操作的&#x…

MySQL数据库增删改查及聚合查询SQL语句学习汇总

目录 数据库增删改查SQL语句 MySQL数据库指令 1.查询数据库 2.创建数据库 3.删除数据库 4.选择数据库 创建表table 查看所有表 创建表 查看指定表的结构 删除表 数据库命令进行注释 增删改查&#xff08;CRUD&#xff09;详细说明 增加 SQL库提供了关于时间的…

Python 查询 DynamoDB

文章目录 DynamoDB 简介Boto3简介安装和导入 Boto3将 Boto3 连接到 DynamoDB 使用 Boto3 在 DynamoDB 中创建表通过 Boto3 删除 DynamoDB 中的表通过 Boto3 列出 DynamoDB 中的表通过 Boto3 在 DynamoDB 中分页通过 Boto3 在 DynamoDB 中排序通过 Boto3 在 DynamoDB 中获取项目…

【设计模式与范式:行为型】63 | 职责链模式(下):框架中常用的过滤器、拦截器是如何实现的?

上一节课&#xff0c;我们学习职责链模式的原理与实现&#xff0c;并且通过一个敏感词过滤框架的例子&#xff0c;展示了职责链模式的设计意图。本质上来说&#xff0c;它跟大部分设计模式一样&#xff0c;都是为了解耦代码&#xff0c;应对代码的复杂性&#xff0c;让代码满足…

Ribbon LoadBalanced底层机制源码探秘

&#x1f34a; Java学习&#xff1a;社区快速通道 &#x1f34a; 深入浅出RocketMQ设计思想&#xff1a;深入浅出RocketMQ设计思想 &#x1f34a; 绝对不一样的职场干货&#xff1a;大厂最佳实践经验指南 &#x1f4c6; 最近更新&#xff1a;2023年6月18日 &#x1f34a; 点…

如何自己开发浏览器js插件

大家都知道在网页控制台编写的js脚本一刷新就没了下面教程教大家如何自己写一个js插件&#xff0c;此教程是小白在网上看到的的确认有效才发出来的&#xff0c;无需借助油猴。 最近工作需要小白研究了一下浏览器插件编写的过程下面分享给大家 步骤 在桌面创建一个文件夹&…

指针与数组---指针与一维数组的关系

C语言的高效得益于它指针功能的强大。然而C语言中的指针和数组的关系似乎很“纠结”&#xff0c;让人爱恨交织。指向数组的指针变量、指针数组等&#xff0c;似乎总是“你中有我&#xff0c;我中有你”。 目录 一、数组名的特殊意义及其在访问数组元素中的作用 二、指针运算…

Linux常用指令和知识(1)

目录 ls cd pwd 相对路径&绝对路径&特殊路径符 mkdir touch-cat-more cp-mv-rm which-find grep-wc 管道符 | echo 重定向符 tail &#x1f636;‍&#x1f32b;️&#x1f618;创作不易, 多多支持 前言: 我们学习的Linux命令, 其实他们的本体就是一个个…

ctf 逆向 专题题解

本文的目标是&#xff0c;记录一些不具备通用性的&#xff0c;或者比较进阶的题目。之前的另一篇文章则用于记录一些基础知识和通用性较强的基本手法。 文章目录 跨科题目buu fungame&#xff1a;reverse与pwn的结合reverseweb 反跟踪Easyhook&#xff1a;hook例题 vm类型总结一…

我的创作纪念日——512

机缘 没想到不知不觉在CSDN创作就512天了&#xff0c;想到一开始就仅仅想在CSDN记笔记&#xff0c;到现在成为一个小博主&#xff0c;认识到了很多志同道合的伙伴&#xff0c;中间创作我也曾经懒惰过&#xff0c;放弃过&#xff0c;但我一次又一次重新进行创作&#xff0c;虽然…

AcWing801: 二进制中1的个数(两种方法详解)

原题引出 方法一&#xff1a;使用lowbit 算法的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)&#xff0c;使用lowbit操作&#xff0c;每次操作截取一个数字的最后一个1后面的所有位&#xff0c;每次减去lowbit得到的数字&#xff0c;直到数字减到0&#xff0c;就得到了最终…

【MySQL】选择专题(七)

文章目录 选择题选择题 在关系R ( R # , RN , S # )和S ( S # , SN , SD )中, R 的主码是R # , S 的主码是S #,则S#在R 中称为( A )。 A 外码 B 候选码 C 主码 D 超码 设关系R和S的属性个数分别为2和3,那么等价于( B )。 A. σ1<2(RS) B. σ1<4(RS) C. σ1<2(R…

我们世界中的计算机——从大师视角诠释计算常识

计算机和通信系统&#xff0c;以及由它们所实现的许多事物遍布我们周围。其中一些在日常生活中随处可见&#xff0c;比如笔记本电脑、手机和互联网。今天&#xff0c;在任何公共场所&#xff0c;都会看到许多人在使用手机查询交通路线、购物以及和朋友聊天。与此同时&#xff0…

【大数据】大数据相关概念

文章目录 大数据&#xff1a;一种规模大到在获取、存储、管理、分析方面大大超出了传统数据库软件工具能力范围的数据集合&#xff0c;具有海量的数据规模、快速的数据流转、多样的数据类型以及价值密度四大特征。Hadoop&#xff1a;是一个能够对大量数据进行分布式处理的软件框…

15-3.自定义组件的生命周期函数

目录 1 组件自身的生命周期函数 1.1 使用lifetimes声明生命周期函数 1.2 不使用lifetimes声明生命周期函数 2 组件所在页面的生命周期函数 1 组件自身的生命周期函数 created 组件实例刚刚被创建后执行&#xff0c;可以理解为 html模板刚刚搞好attached 组件被放入节…

万物的算法日记|第六天

笔者自述&#xff1a; 一直有一个声音也一直能听到身边的大佬经常说&#xff0c;要把算法学习搞好&#xff0c;一定要重视平时的算法学习&#xff0c;虽然每天也在学算法&#xff0c;但是感觉自己一直在假装努力表面功夫骗了自己&#xff0c;没有规划好自己的算法学习和总结&am…

DJ4-2 数据报网络和虚电路网络

目录 一、连接和无连接服务 二、数据报网络 1、数据报网络的转发表 2、数据报网络的特点 三、虚电路网络 (Virtual Circuits)* 1、虚电路网络的工作方式 2、虚电路网络的特点 一、连接和无连接服务 任何网络中的网络层只会提供两种服务之一&#xff0c;不会同时提供 数…

Mysql数据库之事务(山高水远,他日江湖再见)

文章目录 一、事务的概念二、事务的ACID特点1.原子性&#xff08;Atomicity&#xff09;2.一致性&#xff08;Consistency&#xff09;3.隔离性&#xff08;lsolation&#xff09;4.持久性&#xff08;Durability) 三、并发访问表的一致性问题和事务的隔离级别1.并发访问表的一…

融合模型stacking14条经验总结和5个成功案例(互联网最全,硬核收藏)_机器学习_人工智能_模型竞赛_论文参考

我看了很多关于融合模型stacking文章&#xff0c;很多作者倾向于赞美融合模型stacking&#xff0c;对其缺点轻描淡写&#xff0c;这容易误导初学者。一叶障目就是这意思。 我的很多学员喜欢用融合模型作为论文或专利创新点&#xff0c;这是一个热门技术。 最近有个同学在论文…

设计模式之单例模式笔记

设计模式之单例模式笔记 说明Singleton(单例)目录单例模式之饿汉式-静态成员变量写法测试类 单例模式之饿汉式-静态代码块写法测试类 单例模式之懒汉式-线程不安全写法和线程安全写法测试类 单例模式之懒汉式-双重检查锁方式(推荐使用的方式)单例模式之懒汉式-静态内部类方式(推…