当前位置: 首页 > news >正文

Java 异步计算

CompletableFuture(可完成的Future)

一个可完成的Future,在我们调用他的get方法的时候,他会阻塞等待这个任务完成来获取他的结果。
当然也可以为这个任务注册一些回调,类似于完成时,出现异常时,或者执行超时等额外处理。

使用

CompletableFuture.suppleAsync

异步执行一个任务并返回结果

CompletableFuture.runAsync

异步执行一个任务不返回结果

这两方法都可以为我们快速的创建一个CompletableFuture对象

CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {System.out.println(Thread.currentThread().getName() + ":supplyAsync start");return "supplyAsync";
});CompletableFuture<String> completableFuture = CompletableFuture.runAsync(() -> {System.out.println(Thread.currentThread().getName() + ":runAsync start");return "runAsync";
});

这两个方法都是可以有第二个参数的,也就是可以执行线程池,这里默认是**Fork-Join-Pool**(一个可以将一个大任务很自然的分解为多个子任务的线程池)。

回调有哪些

方法参数描述
thenApplyT -> U对结果进行处理,并返回一个新的结果
thenAccpetT -> void对结果进行处理,返回结果为Void
thenComposeT -> CompletableFuture对结果调用这个函数来进行处理,并返回一个新的结果
handle(T,Throwable) -> U与thenApply类似,但是他可以处理异常,根据异常对象是否为null,可以判断是否出现异常。
不报错也会执行
whenCompletable(T,Throwable) -> void类似handle 但是不返回结果
不报错也会执行
exceptionallyThrowable -> U出现异常时,返回一个结果
报错时才会执行。
completableOnTimeoutT, long, TimeUnit如果超时返回一个指定的结果。
超时后的链式操作都不执行
orTimeoutlong, TimeUnit超时返回一个异常 TimeOutException
超时后的链式操作都不执行
thenRunRunable执行Runable,返回void,对于不需要任务的返回结果

示例

private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(10, 10, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(50));public static void main(String[] args) {CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {System.out.println(Thread.currentThread().getName() + ":supplyAsync");return "supplyAsync";});completableFuture.thenApply((result) -> {System.out.println(Thread.currentThread().getName() + ":thenApply1 ");return result + "\nthenApply1";}).thenAccept((result) -> {System.out.println(Thread.currentThread().getName() + ":thenAccept ");}).thenCompose(result ->CompletableFuture.supplyAsync(() -> {try {System.out.println(Thread.currentThread().getName() + ":thenCompose ");TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {throw new RuntimeException(e);}return result + "\nthenCompose";}))// thenCompose 超时了,orTimeout 之前的的操作都将被忽略 之后的还会执行.thenAccept((result) -> {System.out.println(Thread.currentThread().getName() + ":ignore ");})// .completeOnTimeout("completeOnTimeout", 1, TimeUnit.SECONDS)// 这里会抛出一个TimeOutException.orTimeout(1, TimeUnit.SECONDS)// throwable则可以获取到 TimeOutException .handleAsync((result, throwable) -> {System.out.println(Thread.currentThread().getName() + ":handleAsync  ");if (throwable == null) {return result;}throwable.printStackTrace();return result + "\nhandleAsync";}, THREAD_POOL_EXECUTOR)// 因为TimeOutException 被handleAsync处理了,所以这里也没有异常了throwable为null.whenComplete((result, throwable) -> {System.out.println(Thread.currentThread().getName() + ":whenComplete  ");if (throwable == null) {return;}throwable.printStackTrace();}).thenRun(() -> {System.out.println(Thread.currentThread().getName() + ":thenRun ");});try {Thread.sleep(5000); // 添加短暂的延迟  因为是异步任务这里不等待一下的话main线程就终止了} catch (InterruptedException e) {e.printStackTrace();}THREAD_POOL_EXECUTOR.shutdownNow();
}#### 执行结果
ForkJoinPool.commonPool-worker-3:supplyAsync
ForkJoinPool.commonPool-worker-3:thenApply1 
ForkJoinPool.commonPool-worker-3:thenAccept 
ForkJoinPool.commonPool-worker-3:thenCompose 
pool-1-thread-1:handleAsync  
pool-1-thread-1:whenComplete  
pool-1-thread-1:thenRun 
java.util.concurrent.TimeoutException

注意回调时机即可。

Async回调

我们这里使用一个叫handleAsync的方法与普通的handle相比,他是执行的线程发送了变化。
使用Async在大多数情况下都会是在一个新的线程下去帮我们执行这个回调,而普通的则是在原有由原有执行任务的线程去执行这个回调。
这里的大多数情况是指我们在使用自定义线程池的时候。而我们的Fork-Join-Pool可能会为一些短暂的任务重用相同的线程,以减少线程的创建和销毁开销。

get、join

当我们的CompletableFuture提供了返回值的时候,我们可以通过get或者join方法来阻塞的得到这个结果
与之不同是get他可能会抛出异常,而join不会。通常我们使用join

组合CompletableFuture

可以根据某种条件去执行两个或者多个CompletableFuture
因为组合太多,这里就简单描述下我自己比较常用的

方法参数描述
static allOfCompletableFuture<?>…所以任务都执行完成后完成,返回结果为void
static anyOfCompletableFuture<?>…任意任务都执行完成后完成,返回结果为void

示例

public static void main(String[] args) {// 1.两个任务都执行完成后才完成CompletableFuture.allOf(CompletableFuture.runAsync(()->{System.out.println("supplyAsync1");}),CompletableFuture.runAsync(()->{// 异步任务等待1秒try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("supplyAsync2");}));// 任意一个完成则完成CompletableFuture.anyOf(CompletableFuture.runAsync(()->{System.out.println("supplyAsync3");}),CompletableFuture.runAsync(()->{// 异步任务等待2秒try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("supplyAsync4");}));// 主线程只等待一秒 try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}
}### 结果
supplyAsync1
supplyAsync3
supplyAsync2

allOf 因为需要两个都完成所以等待一秒后完成输出supplyAsync1、supplyAsync2
antOf 任意一个完成则算结束。因为第二个等待两秒,主线程已经结束了,main已经退出了,所以只输出supplyAsync3

http://www.lryc.cn/news/131696.html

相关文章:

  • 【FAQ】调用视频汇聚平台EasyCVR的iframe地址,视频无法播放的原因排查
  • ⛳ TCP 协议面试题
  • C 语言的字符串函数 puts()
  • Flutter如何知道页面/组件可见?
  • 【MySQL】如何使用Named Pipe协议(Windows)连接MySQL数据库
  • 【c++】c++的一些技术操作
  • JS中对象数组深拷贝方法
  • 2022数学建模国赛C题官网展示论文C155论文复现
  • 阿里云 K8s PVC 绑定 StorageClass 申领 PV 失败
  • php数组
  • 构造不包含字母和数字的webshell
  • 中国大学生服务外包创新创业大赛丨借 AI 之力,助“记账”难题
  • MacOS 安装Redis并设置密码
  • 函数的参数作为引用
  • 【文化课学习笔记】【化学】非金属及其化合物
  • Unity进阶–通过PhotonServer实现联网登录注册功能(客户端)–PhotonServer(三)
  • 步步向前,曙光已现:百度的大模型之路
  • 常见的 Python 错误及其解决方案
  • 文章评论以及回复评论邮件通知(Go 搭建 qiucode.cn 之八)
  • java面试基础 -- ArrayList 和 LinkedList有什么区别, ArrayList和Vector呢?
  • matlab 点云最小二乘拟合空间直线(方法一)
  • 详解junit
  • Nginx的安装及负载均衡搭建
  • JVM学习笔记(一)
  • fastjson 序列化问题:Comparison method violates its general contract
  • Angular安全专辑之二——‘unsafe-eval’不是以下内容安全策略中允许的脚本源
  • 十一、Linux用户及用户组的权限信息如何查看?如何修改?什么是权限的数字序号?
  • ahooks.js:一款强大的React Hooks库及其API使用教程(二)
  • ARM 配置晶振频率
  • 最强自动化测试框架Playwright(37)-网络