Java异步方法CompletableFuture类的使用

Java中常用的异步方法

1、使用线程:你可以创建一个新的线程来执行异步操作。这可以通过直接创建Thread对象并启动它,或者使用线程池来管理线程的生命周期。

new Thread(() -> {// 异步操作代码
}).start();

2、使用线程池Executor框架:Executor框架提供了一种更高级别的异步执行机制,可以管理线程池和任务调度。

ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> {// 异步操作代码
});
executor.shutdown();

3、使用Java 8引入的CompletableFuture类:CompletableFuture类提供了一种更便捷的方式来执行异步操作,并处理操作完成后的结果。

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {// 异步操作代码
});// 可以在异步操作完成后执行回调函数
future.thenRun(() -> {// 操作完成后的处理代码
});

4、使用第三方库:除了Java内置的工具,还有许多第三方库可用于实现异步操作,例如Guava的ListenableFuture等。

CompletableFuture类使用

CompletableFuture 类是 Java 中用于处理异步编程的强大工具。下面是 CompletableFuture 类的一些常用方法的详细解释: 

1.  supplyAsync(Supplier<U> supplier) :创建一个 CompletableFuture,该 CompletableFuture 会异步执行 Supplier 方法,并返回计算结果。  

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {// 异步操作:计算两个整数的和int a = 5;int b = 10;return a + b;
});
// get() 方法,该方法是阻塞的,直到异步操作完成或超时。
Integer val = future.get();
System.out.println("获取异步加载的值:" + val);

2.  thenApply(Function<? super T,? extends U> fn) :在 CompletableFuture 完成后应用给定的函数 fn,将 CompletableFuture 的结果转换为另一种类型,并返回一个新的 CompletableFuture。  

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {// 异步操作:获取用户年龄return getUserAge();
}).thenApply(age -> {// 将年龄转换为字符串return "返回用户年龄信息: " + String.valueOf(age);
});

3.  thenAccept(Consumer<? super T> action) :在 CompletableFuture 完成后执行给定的动作 action,对 CompletableFuture 的结果进行消费,但不返回新的 CompletableFuture。  

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {// 异步操作:获取用户年龄return getUserAge();
}).thenAccept(age -> {// 没有返回值System.out.println("thenAccept没有返回值: " + String.valueOf(age));
});

4.  thenRun(Runnable action) :在 CompletableFuture 完成后执行给定的动作 action,对 CompletableFuture 的结果不进行消费,也不返回新的 CompletableFuture。  

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {// 返回值return "Result";
});CompletableFuture<Void> thenRunFuture = future.thenRun(() -> {// 使用 thenRun() 执行一个操作,在计算完成后打印一条消息System.out.println("执行完成!");
});// 获取值
thenRunFuture.get();

5.  thenCompose(Function<? super T,? extends CompletionStage<U>> fn) :在 CompletableFuture 完成后应用给定的函数 fn,将 CompletableFuture 的结果传递给该函数,并返回一个新的 CompletableFuture。简单的说就是用于将两个 CompletableFuture 对象串联起来执行。

// 使用场景:
// 假设有两个异步任务,任务 A 返回一个结果,任务 B 根据任务 A 的结果进行计算并返回最终结果。
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> {// 异步任务 Areturn 2;
});CompletableFuture<Integer> futureB = futureA.thenCompose(resultA -> {// 异步任务 B,根据任务 A 的结果进行计算int resultB = resultA * 3;return CompletableFuture.completedFuture(resultB);
});// 最终结果输出6
futureB.thenAccept(finalResult -> System.out.println("最终结果:" + finalResult));

6.  exceptionally(Function<Throwable,? extends T> fn) :在 CompletableFuture 发生异常时应用给定的函数 fn,返回一个新的 CompletableFuture,该 CompletableFuture 的结果是由异常处理函数提供的,用于处理异步任务中的异常情况.

// 使用场景:
// 假设有一个异步任务,计算两个数的商,出现除零异常。在发生异常时返回一个默认值
CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {int dividend = 10;int divisor = 0;return dividend / divisor;
});CompletableFuture<Double> resultFuture = future.exceptionally(ex -> {System.out.println("发生异常:" + ex);return 0.0; // 返回默认值
});// 输出:
// 发生异常:java.lang.ArithmeticException: / by zero
// 计算结果:0.0
resultFuture.thenAccept(result -> System.out.println("计算结果:" + result));

7.  handle(BiFunction<? super T,Throwable,? extends U> fn) :在 CompletableFuture 完成后应用给定的函数 fn,无论 CompletableFuture 是否发生异常,该函数都会被调用,并返回一个新的 CompletableFuture,用于处理异步任务的结果(包括正常结果和异常情况)。

CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {int dividend = 10;int divisor = 2;return dividend / divisor;
});CompletableFuture<String> resultFuture = future.handle((result, ex) -> {if (ex != null) {System.out.println("发生异常:" + ex);return "默认值"; // 返回默认值} else {return "计算结果:" + result;}
});// 输出:
// 计算结果:5.0
resultFuture.thenAccept(result -> System.out.println(result));

8.  allOf(CompletableFuture<?>... cfs) :等待多个 CompletableFuture 完成,并返回一个新的 CompletableFuture,该新的 CompletableFuture 在所有输入的 CompletableFuture 都完成后才会完成。 

注意:allOf() 方法返回的是 CompletableFuture<Void> ,因为它只关注所有CompletableFuture的完成状态,而不关心具体的结果。如果你需要获取每个CompletableFuture的结果,你可以在 allOf() 之后使用 get() 方法来获取每个CompletableFuture的结果。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;public class CompletableFutureExample {public static void main(String[] args) {CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return "Result from Future 1";});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "Result from Future 2";});CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}return "Result from Future 3";});CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);try {allFutures.get();System.out.println("所有任务都完成了,开始获取值:");System.out.println("获取 Future 1 的值: " + future1.get());System.out.println("获取 Future 2 的值: " + future2.get());System.out.println("获取 Future 3 的值: " + future3.get());} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}
}

9.  anyOf(CompletableFuture<?>... cfs) :等待多个 CompletableFuture 中的任意一个完成,并返回一个新的 CompletableFuture,该新的 CompletableFuture 在其中任意一个 CompletableFuture 完成时就会完成。 

CompletableFuture.anyOf() 方法常用于以下场景:当你想并发执行多个异步任务,并且只需要获取第一个完成的任务的结果时,它非常有用。在有多个独立任务且只关心第一个成功完成的任务结果时,它可以发挥作用。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;public class CompletableFutureExample {public static void main(String[] args) {CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return "Result from Future 1";});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return "Result from Future 2";});CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}return "Result from Future 3";});CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2, future3);try {System.out.println("打印任务的完成状态: " + anyFuture.isDone());Object result = anyFuture.get();System.out.println("有一个任务完成了,就不管别的任务了: " + result);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}}
}

Future 和 AsyncResult的区别和使用场景

1. Future 接口: 
   - Future 接口是 Java 提供的一个异步操作的结果的占位符。它表示一个可能完成或者失败的异步操作。 
   - Future 接口提供了一些方法(如  get() 、 isDone() 、 cancel()  等)来获取异步操作的结果、检查操作是否完成以及取消操作。 
   - Future 接口的一个主要限制是它只能通过轮询来判断异步操作是否完成,这样可能会导致线程阻塞。 

// get()获取值
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, World!");
String result = future.get();
System.out.println("阻塞直到获取值" + result);// isDone()是否完成
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, World!");
boolean done = future.isDone();
System.out.println("任务是否完成:" + done);// cancel()取消异步任务的执行
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {// 模拟一个长时间运行的任务try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}return "Hello, World!";
});
boolean canceled = future.cancel(true);
System.out.println("任务是否被取消:" + canceled);

2. AsyncResult 接口: 
   - AsyncResult 接口是 Vert.x 框架中的一个特定实现,用于表示异步操作的结果。 
   - AsyncResult 接口继承自 Future 接口,并提供了更多的方法和功能,使得处理异步操作更加方便。 
   - AsyncResult 接口提供了一种更灵活的方式来处理异步操作的结果,包括处理成功和失败的情况,并可以获取操作的异常信息。 

// 此处使用了异步注解、结合AsyncResult使用的举例
@Async(THREAD_NAME)
public Future<Integer> ruleTotal() {return new AsyncResult<Integer>(testMapper.obtainCount());
}

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

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

相关文章

Spring Boot 支持多种环境,包括开发环境、测试环境、预发布环境和生产环境。

Spring Boot 支持多种环境&#xff0c;包括开发环境、测试环境、预发布环境和生产环境。不同的环境具有不同的配置&#xff0c;可以在不同的环境中对应用程序进行测试、验证和部署。以下是每种环境的用途和相应的代码案例。 开发环境 开发环境是开发人员在本地进行开发的环境&…

AI Chat 设计模式:15. 桥接模式

本文是该系列的第十五篇&#xff0c;采用问答式的方式展开&#xff0c;问题由我提出&#xff0c;答案由 Chat AI 作出&#xff0c;灰色背景的文字则主要是我的一些思考和补充。 问题列表 Q.1 如果你是第一次接触桥接模式&#xff0c;那么你会有哪些疑问呢&#xff1f;A.1Q.2 什…

内网隧道—HTTP\DNS\ICMP

本文仅限于安全研究和学习&#xff0c;用户承担因使用此工具而导致的所有法律和相关责任&#xff01; 作者不承担任何法律和相关责任&#xff01; HTTP隧道 Neo-reGeorg Neo-reGeorg 是一个旨在积极重构 reGeorg 的项目&#xff0c;目的是&#xff1a; 提高可用性&#xff0…

山西电力市场日前价格预测【2023-08-17】

日前价格预测 预测明日&#xff08;2023-08-17&#xff09;山西电力市场全天平均日前电价为376.70元/MWh。其中&#xff0c;最高日前电价为431.75元/MWh&#xff0c;预计出现在19: 45。最低日前电价为339.25元/MWh&#xff0c;预计出现在13: 15。 价差方向预测 1&#xff1a; 实…

python实现抽奖小程序

使用Python的Tkinter库来添加抽奖程序的界面操作。下面是一个示例代码&#xff1a; import random import tkinter as tkdef lottery():prizes [一等奖, 二等奖, 三等奖, 谢谢参与]winner random.choice(prizes)result_label.config(text恭喜您获得了{}&#xff01;.format(…

未出现过的最小正整数

给定一个长度为 n 的整数数组&#xff0c;请你找出未在数组中出现过的最小正整数。 样例 输入1&#xff1a;[-5, 3, 2, 3]输出1&#xff1a;1输入2&#xff1a;[1, 2, 3]输出2&#xff1a;4数据范围 1≤n≤105 , 数组中元素的取值范围 [−109,109]。 代码&#xff1a; c…

MySql主从复制1032错误(Slave_IO_Running: Yes Slave_SQL_Running: No)

MySql主从复制1032错误&#xff08;Slave_IO_Running: Yes Slave_SQL_Running: No&#xff09; Slave_IO_Running: Yes Slave_SQL_Running: No报错&#xff1a; Last_SQL_Error: Could not execute Delete_rows event on table hr.test; Can’t find record in ‘test’, Erro…

【Unity造轮子】制作一个简单的2d抓勾效果(类似蜘蛛侠的技能)

文章目录 前言开始1. 实现简单的抓勾效果2. 高阶钩爪效果 源码参考完结 前言 欢迎阅读本文&#xff0c;本文将向您介绍如何使用Unity游戏引擎来实现一个简单而有趣的2D抓勾效果&#xff0c;类似于蜘蛛侠的独特能力。抓勾效果是许多动作游戏和平台游戏中的常见元素&#xff0c;…

【AI绘画】3分钟学会ikun幻术图

目录 前言一、效果展示二、准备工作三、操作步骤3.1平台创建实例3.2 启动SD 四、安装QR Code Monster 模型五、成图 前言 大家热爱的ikun幻术在今天的分享中将呈现。在本文中&#xff0c;我们将揭示一个备受欢迎的图像幻术技术&#xff0c;让您感受到令人惊叹的视觉创造力。 …

springboot+vue游戏攻略推荐网站的设计与开发_s5832

热门网游推荐网站是一个利用JAVA技术建设的网上管理系统&#xff0c;在热门网游推荐管理中实现信息化。系统的设计就是为了迎合广大用户需求而创建的一个界面简洁、有定向内容、业务逻辑简单易操作的热门网游推荐网站。本文以热门网游推荐为例&#xff0c;提出了利用JAVA技术设…

Angular中的ActivatedRoute和Router

Angular中的ActivatedRoute和Router解释 在Angular中&#xff0c;ActivatedRoute和Router是两个核心的路由服务。他们都提供可以用来检查和操作当前页面路由信息的方法和属性。 ActivatedRoute ActivatedRoute是一个保存关于当前路由状态&#xff08;如路由参数、查询参数以…

Linux下grep通配容易混淆的地方

先上一张图: 我希望找到某个版本为8的一个libXXX.8XXX.so ,那么应该怎么写呢? 先看这种写法对不对: 是不是结果出乎你的意料之外? 那么我们来看一下规则: 这里的 "*" 表示匹配前一个字符的零个或多个 于是我们就不难理解了: lib*8*.so 表示 包…

医疗PACS源码,支持三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜

C/S架构的PACS系统源码&#xff0c;PACS主要进行病人信息和影像的获取、处理、存储、调阅、检索、管理&#xff0c;并通过网络向全院提供病人检查影像及诊断报告&#xff1b;各影像科室之间共享不同设备的病人检查影像及诊断报告;在诊断工作站上&#xff0c;调阅HIS中病人的其它…

拒绝摆烂!C语言练习打卡第二天

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;每日一练 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、选择题 &#x1f4dd;1.第一题 &#x1f4dd;2.第二题 &#x1f4dd;…

P1304 哥德巴赫猜想

题目描述 输入一个偶数 N N N&#xff0c;验证 4 ∼ N 4\sim N 4∼N 所有偶数是否符合哥德巴赫猜想&#xff1a;任一大于 2 2 2 的偶数都可写成两个质数之和。如果一个数不止一种分法&#xff0c;则输出第一个加数相比其他分法最小的方案。例如 10 10 10&#xff0c; 10 …

Springboot写单元测试

导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintag…

django实现悲观锁乐观锁

前期准备 # 线上卖图书-图书表 图书名字&#xff0c;图书价格&#xff0c;库存字段-订单表&#xff1a; 订单id&#xff0c;订单名字# 表准备class Book(models.Model):name models.CharField(max_length32)price models.IntegerField() #count models.SmallIntegerField…

Python实时监控键盘的输入并打印出来

要实现Python实时监控键盘的输入并打印出来&#xff0c;可以使用pynput模块。 首先&#xff0c;需要安装pynput模块&#xff1a; pip install pynput 然后&#xff0c;可以编写以下代码来实现实时监控键盘输入并打印出来的功能&#xff1a; from pynput import keyboard# 定…

【Unity每日一记】方位辨别—向量的叉乘点乘结合

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…