CompletableFuture使用示例

2023-05-16

不进行异常处理

1、runAsync() 无返回值 supplyAsync() 有返回值
在这里插入图片描述
根据idea的提示和变量的范型也能看出来,runAsync() 是不返回值的,而supplyAsync则会把比较的结果返回出去.

2、thenApply()、thenAccept()、thenRun按顺序执行异步任务
如果一个异步任务的完成需要依赖前一个异步任务的完成,那么可以使用这三个方法,不需要先调用get()方法获取返回值后再执行.
这三个方法的区别:
在这里插入图片描述
代码示例
在这里插入图片描述
执行结果:
在这里插入图片描述
thenApply和thenApplyAsync的区别
我们发现这三个方法都有一个对应的带有后缀Async的方法.
那么带Async和不带Async有什么不同呢?用thenApply和thenApplyAsync来比较,这两个方法区别就在于谁去执行这个任务.
如果使用thenApplyAsync,那么执行的线程是从ForkJoinPool.commonPool()中获取不同的线程进行执行.
如果使用thenApply,则需要分情况讨论:

  1. supplyAsync方法执行速度特别快,那么thenApply任务就是主线程进行执行
  2. supplyAsync方法执行速度特别慢,那么就和supplyAsync执行线程一样.
        System.out.println("-------------");
        CompletableFuture<String> supplyAsyncWithSleep = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "supplyAsyncWithSleep Thread Id : " + Thread.currentThread();
        });
        CompletableFuture<String> thenApply = supplyAsyncWithSleep
            .thenApply(name -> name + "------thenApply Thread Id : " + Thread.currentThread());
        CompletableFuture<String> thenApplyAsync = supplyAsyncWithSleep
            .thenApplyAsync(name -> name + "------thenApplyAsync Thread Id : " + Thread.currentThread());
        System.out.println("Main Thread Id: "+ Thread.currentThread());
        System.out.println(thenApply.get());
        System.out.println(thenApplyAsync.get());
        System.out.println("-------------No Sleep");
        CompletableFuture<String> supplyAsyncNoSleep = CompletableFuture.supplyAsync(()->{
            return "supplyAsyncNoSleep Thread Id : " + Thread.currentThread();
        });
        CompletableFuture<String> thenApplyNoSleep = supplyAsyncNoSleep
            .thenApply(name -> name + "------thenApply Thread Id : " + Thread.currentThread());
        CompletableFuture<String> thenApplyAsyncNoSleep = supplyAsyncNoSleep
            .thenApplyAsync(name -> name + "------thenApplyAsync Thread Id : " + Thread.currentThread());
        System.out.println("Main Thread Id: "+ Thread.currentThread());
        System.out.println(thenApplyNoSleep.get());
        System.out.println(thenApplyAsyncNoSleep.get());

执行结果
在这里插入图片描述
3、thenCompose()、thenCombine()
thenCompose():可以用于组合多个CompletableFuture,将前一个结果作为下一个计算的参数,他们之间存在先后顺序
thenCombine():两个任务是并行执行的,最后将结果汇总.

        // thenCompose
        CompletableFuture<String> thenCompose = CompletableFuture.supplyAsync(() -> "hello").thenCompose(s -> CompletableFuture.supplyAsync(()-> s + "world"));
        System.out.println("thenCompose = " + thenCompose.get());
        // thenCombine
        CompletableFuture<String> hello = CompletableFuture.supplyAsync(() -> "hello");
        CompletableFuture<String> world = CompletableFuture.supplyAsync(() -> "world");
        CompletableFuture<String> thenCombine = hello.thenCombine(world ,(h,w)-> h + w);
        System.out.println("thenCombine = " + thenCombine.get());
        

执行结果:
在这里插入图片描述
其中我们能看到thenCombine、thenCompose其实就是组合了两个异步操作,那么如何做到组合任意多个异步操作呢?
allOf():等待所有CompletableFuture完成以后才会运行回调函数
anyOf():只要其中一个CompletableFuture完成,那么就会执行回调函数.注意此时其他的任务也就不执行了.

		// allOf
        CompletableFuture<String> hello = CompletableFuture.supplyAsync(() -> "hello");
        CompletableFuture<String> world = CompletableFuture.supplyAsync(() -> "world");
        CompletableFuture<String> statement = CompletableFuture.supplyAsync(() -> "I have two cats!");
        // 等到所有的异步线程都执行完之后,再执行后面的。
        CompletableFuture.allOf(hello, world, statement);
        System.out.println("hello.get() = " + hello.get());
        System.out.println("world.get() = " + world.get());
        System.out.println("statement.get() = " + statement.get());
        
        // anyOf
        CompletableFuture<String> hello1 = CompletableFuture.supplyAsync(() -> "hello");
        CompletableFuture<String> world1 = CompletableFuture.supplyAsync(() -> "world");
        CompletableFuture<String> statement1 = CompletableFuture.supplyAsync(() -> "I have two cats!");
        // objectCompletableFuture:获取到多个线程中第一个执行结束的线程的结果
        CompletableFuture<Object> objectCompletableFuture = CompletableFuture.anyOf(hello1, world1, statement1);
        System.out.println("voidCompletableFuture.get() = " + objectCompletableFuture.get());
        

**

异常处理

**
1、whenComplete、whenCompleteAsync,当CompletableFuture完成计算结果后,我们可能需要对结果进行一些处理.

CompletableFuture.supplyAsync(() -> "hello ")
            .thenApply(s -> s + "world!")
            .whenComplete((result, e) -> System.out.println(result));

执行结果
在这里插入图片描述
可以看到,当线程执行完成的时候,直接打印出了线程运行的结果.
并且可以看到whenComplete其实是有两个值的,一个是结果值,一个是异常信息

CompletableFuture.supplyAsync(() -> {
            int i = 10 / 0;
           return  "hello ";
        }).thenApply(s -> s + "world!")
            .whenComplete((result, e) -> {
                System.out.println(result);
                System.out.println(e);
            });

在这里插入图片描述
2、exceptionally()

CompletableFuture<String> exceptionallyCompletable = CompletableFuture.supplyAsync(() -> {
            int i = 10 / 0;
            return "hello ";
        }).exceptionally(e -> {
            System.out.println(e);
            return "你的小主已下线";
        });
        String exceptionally = exceptionallyCompletable.get();
        System.out.println("exceptionally = " + exceptionally);

在这里插入图片描述

通过上面的代码和返回值可以看出,其可以接收值是异常信息,也能够返回自定义返回值.
没有异常的时候,是不会执行exceptionally()里的方法.

CompletableFuture<String> exceptionallyCompletable = CompletableFuture.supplyAsync(() -> {
          //  int i = 10 / 0;
            return "hello ";
        }).exceptionally(e -> {
            System.out.println(e);
            return "你的小主已下线";
        });
        String exceptionally = exceptionallyCompletable.get();
        System.out.println("exceptionally = " + exceptionally);
    }

在这里插入图片描述

3、handle()
调用handle()方法也能够捕捉到异常并且自定义返回值,但是和exceptionally方法不同的一点是handle()方法无论是否发生异常均会被调用.这点和whenComplete很像.
在这里插入图片描述

CompletableFuture<String> handleCompletable = CompletableFuture.supplyAsync(() -> {
          //  int i = 10 / 0;
            return "hello ";
        }).handle((result,e) -> {
            System.out.println(result);
            System.out.println(e);
            if(Objects.nonNull(e)){
                return "你的小主已下线";
            }
           return result;
        });
        String handle = handleCompletable.get();
        System.out.println("handle = " + handle);

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CompletableFuture使用示例 的相关文章

随机推荐

  • 坐标转换tf

    tf介绍 坐标转换 TransForm 位置和姿态 坐标变换是空间实体的位置描述 xff0c 是从一种坐标系统变换到另一种坐标系统的过程 通过建立两个坐标系统之间一一对应关系来实现下图为机器人几个部件之间的坐标关系 tf概念 tf是一个用户
  • 经典Windows编程书单

    说好的这次写一个图形编程书单 但是看起来不是很好整理 xff0c 这类书散落的家里到处都是 先把经典Windows编程的书整理一下吧 xff0c 不过Windows的也到处都是很多都找不到了 xff0c 只能把找到的拍个照 xff0c 可能
  • vscode设置C++代码格式化(Clang-Format)

    vscode中只要安装了C C 43 43 扩展后 xff0c 在C C 43 43 源文件中右键就能看到格式化文档的选项 xff0c 这样就能通过该选项或者其快捷键 xff08 Shift 43 Alt 43 F xff09 来实现快速格
  • git pull覆盖了本地未push的代码解决方案

    一 问题背景 情况 xff1a 本地代码写完后 xff0c git push上去github xff0c 然后报错 xff0c 提示要先git pull pull之后 xff0c 失败了或者覆盖了本地未push的代码 二 解决方案 2 1
  • FreeRTOS任务调度原理

    1 FreeRTOS的列表和列表项 列表和列表项是FreeRTOS中一个非常重要的数据结构 xff0c 是FreeRTOS的基石 要想看懂FreeRTOS的源码并学习其中的原理 xff0c 我们必须先了解一下这个数据结构 这个数据结构也是和
  • Go语言学习教程(十四)

    一 反射介绍 在Go语言标准库中reflect包提供了运行时反射 程序运行过程中动态操作结构体 当变量存储结构体属性名称 想要对结构体这个属性赋值或查看时 就可以使用反射 反射还可以用作判断变量类型 整个reflect包中最重要的两个类型
  • 正点原子FPGA学习笔记4.4——UART串口通信,基于达芬奇开发板 A7

    目录 1 环回模块 协调发送接收模块 0 综上 xff0c 信号线如下 xff1a 1 捕捉发送模块传过来recv done信号的上升沿 得到recv done flag 2 recv done flag拉高 xff0c 接收了一帧数据 x
  • UBUNTU 下面的DOCKER使用图形界面

    ubuntu下docker容器中开启图形界面 xff1a 转载自 xff1a https blog csdn net ericcchen article details 79253416 方法一 xff1a 开启SSH服务 详细开启流程 x
  • unbuntu 16.04中编译ffmpeg

    1 xff1a 解压 xff1a sudo tar jxvf ffmpeg 3 4 tar gz2 2 xff1a 更新安装 xff1a sudo apt get update 3 xff1a 安装依赖包 xff1a sudo apt ge
  • git仓库命名规范

    git仓库命名规范 对于git仓库 xff0c 对于git仓库 xff0c 名字不可用下述规定的字符 64 amp xff0c lt gt 43 61 这些字符git不认可 xff0c 默认转成 输入 也会显示转换成 xff0c 如下图所示
  • px4之nuttx操作系统编译

    nuttx 嵌入式操作系统 1 下载源码 https nuttx apache org download 分别下载app和os 下载完毕后 xff0c 解压两个压缩包 2 根据当前嵌入式的开发板子 xff0c 进行配置 span class
  • Ubuntu18.04 安装ROS以及汇总rosdep init与rosdep update执行失败的解决方案

    一 前言 我已经装了不知道多少次ROS xff0c 由于学习需要 xff0c 又一次给新机安装ROS xff0c 还是被安装出错折磨了半天 吃一堑长一智 xff0c 为了防止再次安装时要费时全网搜索解决方案 xff0c 本文准备自己记录一下
  • ROS学习01-NVIDIA JETSON TX2 使用Jetpack4.4刷机指南

    ROS学习01 NVIDIA JETSON TX2 使用Jetpack4 4刷机指南 写在前文 最近入手了一台NVIDIA JETSON TX2想做个机器人小车 xff0c 刚拿到板子的时候发现他上面自带安装的是Ubuntu18 04 xf
  • pytorch: 计算网络模型的计算量(FLOPs)和参数量(Params)

    计算量 xff1a FLOPS xff0c 浮点运算次数 xff0c 指运行一次网络模型需要进行浮点运算的次数 参数量 xff1a Params xff0c 是指网络模型中需要训练的参数总数 第一步 xff1a 安装模块 xff08 tho
  • ROS学习02-拿到NVIDIA JETSON TX2该做些什么

    ROS学习02 拿到NVIDIA JETSON TX2该做些什么 在前一片文章中我们已经将NVIDIA JETSON TX2完美的刷机了 ROS学习01 NVIDIA JETSON TX2 使用Jetpack4 4刷机指南 刷完机后连上显示
  • ROS学习09-NVIDIA JETSON TX2安装配置TOF摄像头Intel® RealSense™ Tracking Camera T265

    ROS学习09 NVIDIA JETSON TX2安装配置TOF摄像头Intel RealSense Tracking Camera T265 这一节继续准备我们机器人的器官 xff0c 在惯性导航方面我们选择了Intel RealSens
  • ROS学习12-NVIDIA JETSON TX2 使用turtlebot3 gazebo模拟仿真机器人

    ROS学习12 NVIDIA JETSON TX2 使用turtlebot3 gazebo模拟仿真机器人 这一节我们要使用turtlebot3搭建一个仿真的机器人及环境 xff0c 这里是基于ROS1中的melodic版本 首先安装turt
  • 全方位移动全向轮、麦克纳姆轮底盘运动学逆解详解(内含电机输出方程)

    全方位移动全向轮 麦克纳姆轮底盘运动学逆解详解 xff08 内含电机输出方程 xff09 开始输出方程介绍定义底盘布局快速计算函数主函数最后 开始 智能小车全方位移动底盘常用包括 xff1a 全向轮底盘 xff0c 麦克纳姆轮底盘 xff0
  • 程序员3年5年10年三个阶段

    第一阶段 三年 三年对于程序员来说是第一个门槛 xff0c 这个阶段将会淘汰掉一批不适合写代码的人 这一阶段 xff0c 我们走出校园 xff0c 迈入社会 xff0c 成为一名程序员 xff0c 正式从书本上的内容迈向真正的企业级开发 我
  • CompletableFuture使用示例

    不进行异常处理 1 runAsync 无返回值 supplyAsync 有返回值 根据idea的提示和变量的范型也能看出来 runAsync 是不返回值的 而supplyAsync则会把比较的结果返回出去 2 thenApply thenA