2. CompletableFuture

news2025/2/9 9:55:39

2.1 Future接口理论知识复习
Future接口(FutureTask实现类)定义了操作异步任务执行一些方法,如获取异步任务的执行结果、取消异步任务的执行、判断任务是否被取消、判断任务执行是否完毕等。
举例:比如主线程让一个子线程去执行任务,子线程可能比较耗时,启动子线程开始执行任务后,主线程就去做其他事情了,忙完其他事情或者先执行完,过了一会再才去获取子任务的执行结果或变更的任务状态(老师上课时间想喝水,他继续讲课不结束上课这个主线程,让学生去小卖部帮老师买水完成这个耗时和费力的任务)。
在这里插入图片描述
2.2 Future接口常用实现类FutureTask异步任务
2.2.1 Future接口能干什么
Future是Java5新加的一个接口,它提供一种异步并行计算的功能,如果主线程需要执行一个很耗时的计算任务,我们会就可以通过Future把这个任务放进异步线程中执行,主线程继续处理其他任务或者先行结束,再通过Future获取计算结果。
2.2.2 Future接口相关架构
● 目的:异步多线程任务执行且返回有结果,三个特点:多线程、有返回、异步任务(班长为老师去买水作为新启动的异步多线程任务且买到水有结果返回)
● 代码实现:Runnable接口+Callable接口+Future接口和FutureTask实现类。

在这里插入图片描述


public class CompletableFutureDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask(new MyThread());
        Thread t1 = new Thread(futureTask); //开启一个异步线程
        t1.start();

        System.out.println(futureTask.get()); //有返回hello Callable
    }
}


class MyThread implements Callable<String> {

    @Override
    public String call() throws Exception {
        System.out.println("--------come in");
        return "hello Callable";
    }
}

2.2.3 Future编码实战和优缺点分析
● 优点: Future+线程池异步多线程任务配合,能显著提高程序的运行效率。
● 缺点:

○ get()阻塞—一旦调用get()方法求结果,一旦调用不见不散,非要等到结果才会离开,不管你是否计算完成,如果没有计算完成容易程序堵塞。
○ isDone()轮询—轮询的方式会耗费无谓的cpu资源,而且也不见得能及时得到计算结果,如果想要异步获取结果,通常会以轮询的方式去获取结果,尽量不要阻塞。

● 结论:Future对于结果的获取不是很友好,只能通过阻塞或轮询的方式得到任务的结果。


public class FutureApiDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        FutureTask<String> futureTask = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + "--------come in");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "task over";
        });

        Thread t1 = new Thread(futureTask, "t1");
        t1.start();

//        System.out.println(futureTask.get());//这样会有阻塞的可能,在程序没有计算完毕的情况下。
        System.out.println(Thread.currentThread().getName() + " ------忙其他任务");
//        System.out.println(futureTask.get(3,TimeUnit.SECONDS));//只愿意等待三秒,计算未完成直接抛出异常
        while (true) {//轮询
            if(futureTask.isDone()){
                System.out.println(futureTask.get());
                break;
            }else{
                TimeUnit.MILLISECONDS.sleep(500);
                System.out.println("正在处理中,不要催了,越催越慢");
            }
        }
        /* 轮询结果
        * main ------忙其他任务
        t1--------come in
        正在处理中,不要催了,越催越慢
        正在处理中,不要催了,越催越慢
        正在处理中,不要催了,越催越慢
        正在处理中,不要催了,越催越慢
        正在处理中,不要催了,越催越慢
        正在处理中,不要催了,越催越慢
        正在处理中,不要催了,越催越慢
        正在处理中,不要催了,越催越慢
        正在处理中,不要催了,越催越慢
        正在处理中,不要催了,越催越慢
        task over
        Process finished with exit code 0
        * */
    }
}

2.2.4 完成一些复杂的任务
● 对于简单的业务场景使用Future完全ok
● 回调通知:
○ 应对Future的完成时间,完成了可以告诉我,也就是我们的回调通知
○ 通过轮询的方式去判断任务是否完成这样非常占cpu并且代码也不优雅
● 创建异步任务:Future+线程池组合
● 多个任务前后依赖可以组合处理(水煮鱼—>买鱼—>调料—>下锅):
○ 想将多个异步任务的结果组合起来,后一个异步任务的计算结果需要钱一个异步任务的值
○ 想将两个或多个异步计算合并成为一个异步计算,这几个异步计算互相独立,同时后面这个又依赖前一个处理的结果
● 对计算速度选最快的:
○ 当Future集合中某个任务最快结束时,返回结果,返回第一名处理结果
● 结论:
○ 使用Future之前提供的那点API就囊中羞涩,处理起来不够优雅,这时候还是让CompletableFuture以声明式的方式优雅的处理这些需求。
○ 从i到i++
○ Future能干的,CompletableFuture都能干

2.3 CompletableFuture对Future的改进
2.3.1 CompletableFuture为什么会出现
● get()方法在Future计算完成之前会一直处在阻塞状态下,阻塞的方式和异步编程的设计理念相违背。
● isDene()方法容易耗费cpu资源(cpu空转),
● 对于真正的异步处理我们希望是可以通过传入回调函数,在Future结束时自动调用该回调函数,这样,我们就不用等待结果
jdk8设计出CompletableFuture,CompletableFuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。
2.3.2 CompletableFuture和CompletionStage介绍
类架构说明:
在这里插入图片描述
在这里插入图片描述
2.3.3 核心的四个静态方法,来创建一个异步任务
四个静态构造方法
在这里插入图片描述
对于上述Executor参数说明:若没有指定,则使用默认的ForkJoinPoolcommonPool()作为它的线程池执行异步代码,如果指定线程池,则使用我们自定义的或者特别指定的线程池执行异步代码

public class CompletableFutureBuildDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },executorService);

        System.out.println(completableFuture.get()); //null


        CompletableFuture<String> objectCompletableFuture = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello supplyAsync";
        },executorService);

        System.out.println(objectCompletableFuture.get());//hello supplyAsync

        executorService.shutdown();

    }
}

CompletableFuture减少阻塞和轮询,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。

public class CompletableFutureUseDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "---come in");
            int result = ThreadLocalRandom.current().nextInt(10);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (result > 5) { //模拟产生异常情况
                int i = 10 / 0;
            }
            System.out.println("----------1秒钟后出结果" + result);
            return result;
        }, executorService).whenComplete((v, e) -> {
            if (e == null) {
                System.out.println("计算完成 更新系统" + v);
            }
        }).exceptionally(e -> {
            e.printStackTrace();
            System.out.println("异常情况:" + e.getCause() + " " + e.getMessage());
            return null;
        });
        System.out.println(Thread.currentThread().getName() + "先去完成其他任务");
        executorService.shutdown();
    }
}

/**
 * 无异常情况
 * pool-1-thread-1---come in
 * main先去完成其他任务
 * ----------1秒钟后出结果9
 * 计算完成 更新系统9
 */

/**
 * 有异常情况
 *pool-1-thread-1---come in
 * main先去完成其他任务
 * java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
 * 异常情况:java.lang.ArithmeticException: / by zero java.lang.ArithmeticException: / by zero
 */

CompletableFuture优点:
● 异步任务结束时,会自动回调某个对象的方法
● 主线程设置好回调后,不用关心异步任务的执行,异步任务之间可以顺序执行
● 异步任务出错时,会自动回调某个对象的方法
在这里插入图片描述

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

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

相关文章

python中的map函数

1. map()函数的简介以及语法&#xff1a; 1.1 map是python内置函数&#xff0c;会根据提供的函数对指定的序列做映射。 1.2 map()函数的格式是&#xff1a; map(function,iterable,...) 第一个参数接受一个函数名&#xff0c;后面的参数接受一个或多个可迭代的序列 1.3 map的返…

linux基本功之高效学习Linux命令行工具的技巧:Pandoc实战

前言 大家好&#xff0c;又见面了&#xff0c;我是沐风晓月&#xff0c;本文是专栏【linux基本功-基础命令实战】的第65篇文章。 专栏地址&#xff1a;[linux基本功-基础命令专栏] &#xff0c; 此专栏是沐风晓月对Linux常用命令的汇总&#xff0c;希望能够加深自己的印象&am…

F407之位带操作

位带操作的应用场景&#xff0c;通常在于对IO口进行输入输出读取和控制。 这就和51单片机中直接的端口赋值是一样的。 比如 P0.0 0; P0.0 1; 直接就是对端口P0.0输出0和1。 如何实现呢&#xff1f; 什么是位带操作 位带操作简单的说&#xff0c;就是把每个比特膨胀为一个32位…

全面了解AES加密:入门指南

文章目录 I. 介绍A. 什么是加密B. 为什么要加密1. 保护数据的机密性2. 防止数据被篡改3. 防止数据被窃取4. 保护数据的可信度 C. AES加密的概述 II. 对称加密与非对称加密A. 对称加密的定义和特点1. 简单快速2. 安全性较低3. 适合大量数据加密4. 密钥管理困难5. 用途广泛 B. 非…

黑马版Redis基础篇

一、 初识redis 1.1 认识 NoSQL 关系型数据库&#xff1a; 1.2 认识Redis 二、Redis 常见命令 2.1 Redis 数据结构介绍 2.2 Redis 通用命令 2.3 String 类型 2.3.1 Key的层级格式 2.4 Hash 类型 2.5 List 类型 2.6 Set 类型 2.7 SortedSet 类型 三、Redis 的 Java 客户端 1.…

DelayQueue的核心属性和写入、读取流程分析

DelayQueue的核心属性 DelayQueue的写入流程分析 add方法也是包装使用offer方法。Delay是无解的&#xff0c;数组又可以动态扩容&#xff0c;不需要关注生产者的阻塞问题 offer方法分析 DelayQueue读取流程 消费者消费元素存在两种阻塞的情况&#xff1a; 1.消费者得到栈顶的…

华为OD机试真题 JavaScript 实现【预定酒店】【2022Q4 100分】

一、题目描述 放暑假了&#xff0c;小明决定到某旅游景点游玩&#xff0c;他在网上搜索到了各种价位的酒店(长度为n的 数组A)&#xff0c;他的心理价位是x元&#xff0c;请帮他筛选出k个最接近x元的酒店 (n>k>0) ,并由低到高打印酒店的价格。 二、输入描述 第一行: n,…

chatgpt赋能python:Python怎么开三次方?

Python怎么开三次方&#xff1f; Python是一门常用的高级编程语言&#xff0c;被广泛用于数据分析、人工智能、Web开发等领域。在Python中&#xff0c;我们可以使用几种方法轻松地计算三次方根&#xff0c;例如使用sqrt函数、cbrt函数和简单的数学表达式。本文将介绍三种方法&…

聊聊Scrum三大角色的质量意识和文化建设

这是鼎叔的第六十三篇原创文章。行业大牛和刚毕业的小白&#xff0c;都可以进来聊聊。 欢迎关注本专栏和微信公众号《敏捷测试转型》&#xff0c;星标收藏&#xff0c;大量原创思考文章陆续推出。 参考前文&#xff1a;聊聊Scrum价值观与测试启发 本篇从Scrum的主要角色视角…

开关电源精确到每个元件-分解电源电路

本次讲解电源以一个13.2W电源为例 输入&#xff1a;AC90~264V 输出&#xff1a;3.3V/4A 原理图&#xff1a; 变压器是整个电源供应器的重要核心&#xff0c;所以变压器的计算及验证是很重要的。 1.决定变压器的材质及尺寸: 依据变压器计算公式 2.决定一次侧滤波电容&#…

第五章JMM内存模型

文章目录 计算机硬件存储体系为什么要弄一个 CPU 高速缓存呢&#xff1f;为什么缓存能提高速度呢&#xff1f;缓存带来的问题 Java之JMM模型JMM 是如何抽象线程和主内存之间的关系线程之间如何通信Java 内存区域和 JMM 有何区别 JMM规范下&#xff0c;三大特性原子性可见性有序…

000mysql常用资源推荐

官网 MySQL :: MySQL 8.0 Reference Manualhttps://dev.mysql.com/doc/refman/8.0/en/ 博客 一树一溪 侧重原理https://mp.weixin.qq.com/mp/homepage?__bizMzg3NTc3NjM4Nw&hid2&snb5d65ce17893a722b6748b471412eab0&scene1&devicetypeandroid-33&ver…

Spring-Boot的创建与配置文件

文章目录 前言Spring与SpringBoot的区别SpringBoot的创建与使用 更改国内源配置SpringBoot目录介绍SpringBoot配置文件配置⽂件的格式properties 基本语法yml的基本语法yml的注意事项 properties VS yml 好坏 前言 前面讲述了 ,Spring的概念与使用方法 , 接下来要介绍的是 Spr…

华为OD机试真题 JavaScript 实现【服务中心选址】【2023Q1 100分 】

一、题目描述 一个快递公司希望在一条街道建立新的服务中心。公司统计了该街道中所有区域在地图上的位置&#xff0c;并希望能够以此为依据为新的服务中心选址&#xff0c;使服务中心到所有区域的距离的总和最小。 给你一个数组 positions&#xff0c;其中 positions[i] [le…

B+树:高效存储与索引的完美结合

目录 引言&#xff1a;一、定义&#xff1a;二、B树和B树三、特点&#xff1a;四、应用场景&#xff1a;总结&#xff1a; 引言&#xff1a; 在计算机科学领域中&#xff0c;数据结构的选择对于高效存储和索引数据至关重要。B树&#xff08;B tree&#xff09;作为一种自平衡的…

chatgpt赋能python:Python怎么并排输出

Python怎么并排输出 Python是一种高级编程语言&#xff0c;它受到了全球程序员的欢迎。在Python编程中&#xff0c;经常需要将多个变量或数据一起输出。 本文将介绍Python如何并排输出&#xff0c;使输出内容更加整齐美观&#xff0c;提高代码可读性和可维护性。 使用print(…

Chrome浏览器进程:了解多进程架构优劣的探索

文章目录 I. 介绍简述Chrome浏览器的进程模型和重要性 II. 多进程架构的优劣详述Chrome浏览器的多进程架构分析多进程架构对性能、安全性和稳定性的影响对比单进程架构的优缺点和Chrome浏览器多进程架构的差异 III. Chrome浏览器进程类型和作用解释Chrome浏览器中常见的进程类型…

OpenMMLab-AI实战营第二期——5-1.语义分割与MMSegmentation

文章目录 1. 基本概念1.1 案例演示1.2 应用1.3 语义分割概念 2. 语义分割算法2.1 语义分割基本思路2.1.1 按颜色2.1.2 逐像素分类 2.2 深度学习下的语义分割模型2.2.1 全卷积网络2.2.2 Unet2.2.3 上下文信息与PSPNet模型2.2.4 空洞卷积与DeepLab算法2.2.5 总结2.2.6 前言语义分…

我们该如何应对工作失误(How to Handle Failure at Work)

花时间反思 组织架构心理学家、Audrey Page & Associates执行服务总监&#xff0c;Penelope Faure博士表示&#xff1a;“人们在犯错后情绪往往会十分激动。”不论是因为老板在电子邮件中流露出对你的指责&#xff0c;还是因为你明显的疏忽导致客户利益受损&#xff0c;又…

Android 13(T) Media框架 - 智能指针

Android有一套自己的智能指针管理办法&#xff0c;并且将其运用在源码的各个角落&#xff0c;所以学习Media框架之前&#xff0c;我们有必要先了解下Android智能指针。 本节代码源自于Android 13(T)&#xff0c;参考 (aospxref.com) 1 概述 与智能指针相关的总共有5个类&#…