学习使用CompletableFuture
CompletableFuture
- 一.前言
- 二、学习CompletableFuture
- 1.结果获取方式
- 2.创建CompletableFuture对象
- 3.CompletableFuture 的异步回调功能:thenApply
- 4.运行完成时的代码,即对结果进行消耗:thenAccept
- 5.上一步结果与下一步操作无关系:thenRun
- 6.对2个cf的结果进行组合:thenCompose
- 7.结合2个cf的结果:thenCombine
- 8.消耗两个cf的结果,不返回结果
- 9.取计算速度最快的结果:acceptEither
- 10.计算最快的cf的结果转换:applyToEither
- 11.2个cf都执行完后执行操作:runAfterBoth
- 12.处理cf数组:allOf / anyOf
- 13.异常处理
一.前言
1.JDK5的异步处理方式
在jdk5中,我们通过使用Future和Callable,可以在任务执行完毕后得到任务执行结果,可以使用isDone检测计算是否完成,使用cancle停止执行任务,使用阻塞方法get阻塞住调用线程来获取返回结果。但通过使用阻塞方式来获取执行结果,有两方面弊端,一是违异步编程的初衷,二是Future的异常只能自己内部处理。
2.JDK8的异步处理方式
jdk8中加入了实现类CompletableFuture,用于异步编程。底层做任务使用的是ForkJoin, 顾名思义,是将任务的数据集分为多个子数据集,而每个子集,都可以由独立的子任务来处理,最后将每个子任务的结果汇集起来。它是ExecutorService接口的一个实现,它把子任务分配给线程池(称为ForkJoinPool)中的工作线程。从api文档看,它实现了2个接口CompletionStage和Future。CompletionStage支持lambda表达式,接口的方法的功能都是在某个阶段得到结果后要做的事情。因此,CompletableFuture不仅拥有Future的所有特性,而且还内置了lambda表达式,支持异步回调,结果转换等功能,它有以下Future实现不了的功能:
1)合并两个相互独立的异步计算的结果
2)等待异步任务的所有任务都完成
3)等待异步任务的其中一个任务完成就返回结果
4)任务完成后调用回调方法
5)任务完成的结果可以用于下一个任务。
6)任务完成时发出通知
7)提供原生的异常处理api
二、学习CompletableFuture
1.结果获取方式
CompletableFuture获取结果的方式有如下四个方法:
1)get 阻塞获取结果,实现Future的get接口,显式抛出异常
2)getNow(T valueIfAbsent) 获取执行结果,如果当前任务未执行完成,则返回valueIfAbsent
3)join 执行完成后返回执行结果,或者抛出unchecked异常
4)T get(long timeout, TimeUnit unit) 在有限时间内获取数据
2.创建CompletableFuture对象
1)通过静态方法获取对象

这是一个静态方法,返回一个已经计算好的CompletableFuture,示例如下:

completableFuture还能主动结束运算,并显示处理异常,如下是异步执行的代码:

2)使用工厂方式创建CompletableFuture对象
CompletableFuture主要有以下四个工厂方式创建对象的静态方法:

Supplier是java8函数式编程的一个接口,是一个生产者,可以不接收参数。只有一个get方法返回一个泛型实例。很明显,Async结尾的都是可以异步执行,runAsync接收一个Runnable函数式接口类型参数,不返回计算结果。supplyAsync接收一个函数式接口类型Supplier,可以返回计算结果。以上方法如果不指定执行任务的线程池Executor,则默认使用ForkJoinPool.commonPoolcommonPool执行任务。这些接口都支持lambda实现异步的操作。以下是SupplyAsync异步执行的简单示例:

3.CompletableFuture 的异步回调功能:thenApply
上面的方法,执行任务是异步操作。但是调用线程还在等待结果。我们还可以给cf添加回调方法,在任务执行完成后使用cf的结果再做下一步操作、转换。所以执行以下方法时,cf已经计算完毕。

从参数类型可以看到,这是接收一个cf计算的结果T,经过处理后返回参数类型为U的cf。 其中第一个方法是在cf完成的线程中调用。而带Async将在与调用者cf不同的线程中异步调用。

4.运行完成时的代码,即对结果进行消耗:thenAccept

入参是Consumer,执行Consumer后没有返回结果,所以称为消耗。

结果:a
5.上一步结果与下一步操作无关系:thenRun
在执行cf后,如果得到的结果对下一步没有影响,也就是说下一步的操作并不关心上一步的结果,最终也不返回值,可以使用thenRun,参数传递一个Runnable。


6.对2个cf的结果进行组合:thenCompose

thenCompose方法可以将2个独立的任务进行流水线操作。将当前cf的计算结果作为参数传递给后面的cf。

7.结合2个cf的结果:thenCombine
可以将两个完全不相干的对象的结果整合起来,两项任务可以同时执行,比如一个对外的接口服务,既查询数据库中要查询数据的总量,也要返回具体某一页的数据,可以一个cf负责执行查询总条数count的sql,一个查询一页数据。BiFunction是合并结果数据的函数:

其中T是调用thenCombine的cf的结果数据,U是other的结果,v就是合并的结果类型。

8.消耗两个cf的结果,不返回结果

对于2个cf,我们只想在他们执行完成时,消耗执行结果,但是不做数据返回,我们只是希望当完成时得到通知,此方法与thenCombine相似,只不过返回 CompletableFuture,只做消耗处理。

9.取计算速度最快的结果:acceptEither
针对两个CompletionStage,将计算最快的那个CompletionStage的结果用来作为下一步的消耗。此方法接受Consumer只对结果进行消耗。


10.计算最快的cf的结果转换:applyToEither
针对两个CompletionStage,将计算的快的那个CompletionStage的结果用来作为下一步的转换操作。

fn是对调用applyToEither的调用者和计算最快的那个结果进行处理,传入t类型数据,返回一个CompletionStage。

11.2个cf都执行完后执行操作:runAfterBoth
2个cf都执行完后,执行操作Runnable。Runnable不关心2个cf的执行结果:


12.处理cf数组:allOf / anyOf
以上介绍的都是2个future的组合使用。cf还提供allOf,参数是cf数组,当数组中所有的cf都执行完成时,返回一个CompletableFuture。调用返回的cf的join方法阻塞等待cf数组中所有cf执行完成。anyOf是当cf数组中任意一个cf执行完成后,就返回一个cf。

13.异常处理
在上面手工创建cf对象中,介绍过异常的处理,同样使用工厂创建的cf也具有异常管理机制,不在赘述。
学习使用CompletableFuture的更多相关文章
- 《Java学习笔记(第8版)》学习指导
<Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...
- springboot2 webflux 响应式编程学习路径
springboot2 已经发布,其中最亮眼的非webflux响应式编程莫属了!响应式的weblfux可以支持高吞吐量,意味着使用相同的资源可以处理更加多的请求,毫无疑问将会成为未来技术的趋势,是必学 ...
- [转]springboot2 webflux 响应式编程学习路径
原文链接 spring官方文档 springboot2 已经发布,其中最亮眼的非webflux响应式编程莫属了!响应式的weblfux可以支持高吞吐量,意味着使用相同的资源可以处理更加多的请求,毫无疑 ...
- Reactor 3 学习笔记(1)
Reactor 3 与之前学习的RxJava是同一类(反应式编程)框架,基本概念大致差不多,简单记录一下: Reactor 3 利用了java 8中的CompletableFuture.Stream. ...
- Spring Data Commons 官方文档学习
Spring Data Commons 官方文档学习 -by LarryZeal Version 1.12.6.Release, 2017-07-27 为知笔记版本在这里,带格式. Table o ...
- 20155235 2016-2017-2 《Java程序设计》第7周学习总结
20155235 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 第十二章 Lambda 认识Lambda语法 Lambda语法概览 Lambda表达式与函数 ...
- 20145326 《Java程序设计》第7周学习总结
20145326 <Java程序设计>第7周学习总结 教材学习内容总结 第十二章 一.认识Lambda语法 1.Lambda语法概览 Arrays的sort()方法可以用来排序,只不过你要 ...
- java 与大数据学习较好的网站
C# C#中 Thread,Task,Async/Await,IAsyncResult 的那些事儿!https://www.cnblogs.com/doforfuture/p/6293926.html ...
- 20145230《java学习笔记》第七周学习总结
20145230 <Java程序设计>第7周学习总结 教材学习内容 Lambda语法概览 我们在许多地方都会有按字符串长度排序的需求,如果在同一个方法内,我们可以使用一个byName局部变 ...
随机推荐
- Java嵌套类,内部类和外部类
1.嵌套类,内部类 嵌套类是指被定义在一个类内部的类: JAVA的嵌套类有很多种类:1.静态成员类:2.非静态成员类:3.匿名类:4.局部类:其中,除了静态成员类之外,其他的都是内部类,因为静态成员类 ...
- Linux系统 Centos7 环境基于Docker部署Rocketmq服务
消息队列 基本概述 MQ,Message Queue,基于TCP协议构建的简单协议,区别于具体的通信协议. 基于通信协议定义和抽象的更高层次的通信模型,一般都是生产者和消费者模型,又或者说服务端和客户 ...
- SQLserver-MySQL的区别和用法
对于程序开发人员而言,目前使用最流行的两种后台数据库即为MySQL and SQL Server.这两者最基本的相似之处在于数据存储和属于查询系统.你可以使用SQL来访问这两种数据库的数据,因为它们都 ...
- C#联合WINCC之数据通信
[公众号dotNet工控上位机:thinger_swj] 在工控领域中,WINCC仍然占有很大的市场份额.很多时候我们说学习C#开发上位机可以取代传统的组态软件,两者就像冤家一样,然而,即使是冤家,也 ...
- Java面向对象详解-下
一. static static:静态的,可以用来修饰属性.方法.代码块(或初始化块).内部类 static修饰属性(类变量): 由类创建的所有的对象,都共用这一个属性 当其中一个对象对此属性进行修改 ...
- 保存与恢复变量和模型,tensorflow官方文档阅读笔记
官方中文文档的网址先贴出来:https://tensorflow.google.cn/programmers_guide/saved_model tf.train.Saver 类别提供了保存和恢复模型 ...
- DEX文件解析--3、dex文件字符串解析
一.前言 前两篇文章链接: 1.DEX文件头解析 2.DEX文件校验和解析 PS:前几天检查文件夹的时候发现DEX文件解析还只写了开头,正好找点事情来做,就去接着解析DEX ...
- 学会DevOps 能拿多少工资?DevOps 怎么自学?
落地高薪!DevOps为何受宠? DevOps在近几年的发展势头可谓是迅猛无比,已经有越来越多的企业机构开始尝试落地,从国外的微软谷歌到国内的阿里腾讯,DevOps已经从时髦概念落地最佳实践,进而改变 ...
- 数字图像处理 第四章 P157 小错误
问题 我认为P157中部的卷积公式是错的,f(x)h(x-m)应当写为f(m)h(x-m) 解决方法 为了证明,我就用我蹩脚的python实现一下图4.28左列 源代码如下 import numpy ...
- web自动化 -- js操作(滑动屏幕、修改页面)
一.selenium对 js 的操作方法 1.先定义 js 操作 或者 定义 目标元素 2.执行 js 操作: driver.execute_script(js操作) 或者 ...