Java CompletableFuture
2019独角兽企业重金招聘Python工程师标准>>>
Future(接口)
Future是Java 5添加的类,用来描述一个异步计算的结果.
特点
- 对于结果的获取不是很方便,只能通过阻塞或者轮询的方式得到任务的结果。不能及时地得到计算结果.
- 一旦一个运算操作已经完成,这个运算操作就不能被取消。
方法
- boolean cancel (boolean mayInterruptIfRunning) //取消执行此任务
- a)当当前任务已完成,已被取消,或因为一些其它原因不能被取消,这个操作会失败.
- b)若调用该方法时,任务还未开始,则当前任务应该永远不运行.
- c) mayInterruptIfRunning为true时表示允许中断正在运行的任务.
- d)若此方法被调用,则随后调用的 isCancled (), isDone() 将始终返回true.
boolean isCancled () 若此任务在正常完成前被取消则返回true.
boolean isDone() //当前任务是否完成 可能的情况有:正常完成,异常,取消执行.在这些情况下将会返回true.
V get() throws InterruptedException,ExecutionException //如果必要的话,等待计算完成,并返回其结果 a)返回计算的结果
V get(long timeout,TimeUnit unit) throws InterruptedException,ExecutionException,TimeoutException //如果必要的话,等待计算完成,并返回其结果
- a)timeout:最长等待时间 timeunit:超时的时间单位
- b)若成功,返回计算结果
CompletionStage(接口)及CompletableFuture
CompletableFuture实现了Future及CompletionStage接口,是Java 8 新增的一个类.提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法。
特点
一个Future可以被明确的完成(设置它的值或状态);并且当作为一个CompletionStage使用时可以支持依赖函数和当任务完成时触发相应动作的使用.
当两个或多个线程试图 complete, completeExceptionally或 cancel 一个CompletableFuture时,只有一个线程能成功。
CompletableFuture实现了CompletionStage接口方法中的以下策略:
- a)对所有非异步方法的执行,可以由执行当前的CompletableStage的线程执行,也可以由完成方法的其它调用者执行.
- b) 所有不显式指示参数Executor都使用ForkJoinPool.commonPool()(除非它不支持至少二个并行级别的运算,在这种情况下,将会创建一个新的线程去执行当前任务).为了简化监控,debug,追踪,所有生成的异步任务都标记为CompletableFuture.AsynchronousCompletionTask.接口的一个实例.
- c)所有的CompletionStage方法都是独立于其它共公有方法的.所以一个方法的行为不影响子类中其它重写方法.
- CompletableFuture还实现了Future的以下策略:
- a)因为不像FutureTask直接操作计算从而完成任务,cancel()看做另一种异常完成的表现形式.所以,cancel()方法与 completeExceptionally(new CancellationException())效果相同.方法 isCompletedExceptionally()可以用来确定一个CompletableFuture是否以任何异常形式完成.
内部嵌套类
static interface CompletableFuture.AsynchronousCompletionTask
//一个标识接口,用于标识由异步方法产生的异步任务,可能用于监控,debug,追踪异步活动.
方法
注意:在下文中: 不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其它的线程去执行(如果使用相同的线程池,也可能会被同一个线程选中执行)。
- 不以Async结尾,意味着Action使用相同的线程执行.
- 以Async结尾并且没有指定Executor的方法会使用ForkJoinPool.commonPool()作为它的线程池执行异步代码。
- 若参数中有Executor则使用参数中指定的executor线程池实现..
- 以Runnable函数式接口类型为参数,所以CompletableFuture的计算结果为空。
- 以Supplier< U >函数式接口类型为参数,CompletableFuture的计算结果类型为U。因为方法的参数类型为函数式接口,所以可以使用lambda表达式实现异步任务.(简化代码,经常使用)
可以根据方法的参数的类型来加速你的记忆。Runnable类型的参数会忽略计算的结果,Consumer是纯消费计算结果,BiConsumer会组合另外一个CompletionStage纯消费,Function会对计算结果做转换,BiFunction会组合另外一个CompletionStage的计算结果做转换。
构造方法
public CompletableFuture() //创建一个不完整的CompletableFuture
创建CompletableFuture对象
a)CompletableFuture.completedFuture(U value)是一个静态辅助方法,用来返回一个已经计算好的CompletableFuture。
public static <U> CompletableFuture<U> completedFuture(U value)
b)为异步执行的代码创建CompletableFuture创建对象的静态方法
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
计算结果完成时的处理
(1). 第一组
当CompletableFuture的计算结果完成,或者抛出异常的时候,我们可以执行特定的Action。主要是下面的方法:
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)
- a)Action的类型是BiConsumer<? super T,? super Throwable>,它可以处理正常的计算结果,或者异常情况。
- b)这几个方法都会返回CompletableFuture,当Action执行完毕它的结果后返回原始的CompletableFuture的计算结果或者返回异常。
- c)exceptionally方法返回一个新的CompletableFuture,当原始的CompletableFuture抛出异常的时候,就会触发这个CompletableFuture的计算,调用function计算值,否则如果原始的CompletableFuture正常计算完后,这个新的CompletableFuture也计算完成,它的值和原始的CompletableFuture的计算的值相同。也就是这个exceptionally方法用来处理异常的情况。
(2). 第二组
这一组方法虽然也返回CompletableFuture对象,但是对象的值和原来的CompletableFuture计算的值不同,会生成新的计算结果.当原先的CompletableFuture的值计算完成或者抛出异常的时候,会触发这个CompletableFuture对象的计算,结果由BiFunction参数计算而得。因此这组方法兼有whenComplete和转换(thenAply)的两个功能。
public <U> CompletableFuture<U> handle(BiFunction<? super T,Throwable,? extends U> fn)
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T,Throwable,? extends U> fn)
public <U> CompletableFuture<U> handleAsync(BiFunction<? super T,Throwable,? extends U> fn, Executor executor)
转换
转换时不必因为等待一个计算完成而阻塞着调用线程(比如Future的get()方法),而是告诉CompletableFuture当计算完成的时候请执行某个function。而且我们还可以将这些操作串联起来,或者将CompletableFuture组合起来。
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)
- a)功能:当原来的CompletableFuture计算完后,将结果传递给函数fn,将fn的结果作为新的CompletableFuture计算结果。因此它的功能相当于将CompletableFuture< T >转换成CompletableFuture< U >。
- b):这些转换并不是马上执行的,也不会阻塞,而是在前一个stage完成后继续执行。
- c)与handle的区别在于:handle方法会处理正常计算值和异常,因此它可以屏蔽异常,避免异常继续抛出。而thenApply方法只是用来处理正常值,因此一旦有异常就会抛出。
纯消费(执行action)
public CompletableFuture<Void> thenAccept(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action)
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor)
功能:只对结果执行Action,而不返回新的计算值.
public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action)
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action, Executor executor)
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other, Runnable action)
- a)thenAcceptBoth方法功能:当二个CompletionStage都正常完成计算的时候,就会执行提供的action,它们用来组合另外一个异步的结果.
- b)runAfterBoth是当两个CompletionStage都正常完成计算的时候,执行一个Runnable,这个Runnable并不使用计算的结果。
组合
(1):第一组
public <U> CompletableFuture<U> thenCompose(Function<? super T,? extends CompletionStage<U>> fn)
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T,? extends CompletionStage<U>> fn)
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T,? extends CompletionStage<U>> fn, Executor executor)
- a)功能:这一组方法接受一个Function作为参数,这个Function的输入是当前的CompletableFuture的计算值,返回结果将是一个新的CompletableFuture,这个新的CompletableFuture会组合原来的CompletableFuture和函数返回的CompletableFuture。
- b)thenCompose返回的对象并不一是函数fn返回的对象,如果原来的CompletableFuture还没有计算出来,它就会生成一个新的组合后的CompletableFuture。
(2):第二组
public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor)
- a)用来复合另外一个CompletionStage的结果.
- b)两个CompletionStage是并行执行的,它们之间并没有先后依赖顺序,other并不会等待先前的CompletableFuture执行完毕后再执行。
Either
public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor)
public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other, Function<? super T,U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T,U> fn)
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T,U> fn, Executor executor)
- a)acceptEither方法是当任意一个CompletionStage完成的时候,action这个消费者就会被执行。这个方法返回CompletableFuture< Void >
- b)applyToEither方法是当任意一个CompletionStage完成的时候,fn会被执行,它的返回值会当作新的CompletableFuture< U >的计算结果。
例子:可能输出100,也可能输出200
Random rand = new Random();
CompletableFuture< Integer > future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(10000 + rand.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}return 100;
});
CompletableFuture< Integer > future2 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(10000 + rand.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}return 200;
});
CompletableFuture<String> f = future.applyToEither(future2,i -> i.toString());
辅助方法allOf()和anyOf()
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
- a)这两个方法用来组合多个CompletableFuture。
- b)allOf方法是当所有的CompletableFuture都执行完后执行计算。
- c)anyOf方法是当任意一个CompletableFuture执行完后就会执行计算,计算的结果相同。
anyOf()与applyToEither()的区别:
- a)anyOf()可以接受任意多的CompletableFuture;但applyToEither()只能判断二个VompletableFuture.
- b)anyOf()返回的计算结果是众多CompletableFuture参数中其中一个CompletableFuture的计算结果.;applyToEither返回值的结果是要经过fn处理的.
- c):还有静态方法的区别,线程池的选择等.
转载于:https://my.oschina.net/PrivateO2/blog/1581400
Java CompletableFuture相关推荐
- 20 个使用 Java CompletableFuture的例子
转载自 20 个使用 Java CompletableFuture的例子 这篇文章介绍 Java 8 的 CompletionStage API和它的标准库的实现 CompletableFuture. ...
- Java CompletableFuture.runAfterEither任何一个完成就执行Runnable
Java CompletableFuture.runAfterEither任何一个完成就执行Runnable 假设两个互不相干的任务A和B,只要任何一个完成就触发执行线程Runnable privat ...
- Java CompletableFuture的complete(7)
Java CompletableFuture的complete(7) 先看代码: CompletableFuture<String> future = CompletableFuture. ...
- 20个使用 Java CompletableFuture的例子
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者 | 鸟窝 来源 | https://urlify.cn/ay ...
- 使用JAVA CompletableFuture实现流水线化的并行处理,深度实践总结
大家好,又见面啦. 在项目开发中,后端服务对外提供API接口一般都会关注响应时长.但是某些情况下,由于业务规划逻辑的原因,我们的接口可能会是一个聚合信息处理类的处理逻辑,比如我们从多个不同的地方获取数 ...
- Java并发编程有多难?这几个核心技术你掌握了吗?
本文主要内容索引 1.Java线程 2.线程模型 3.Java线程池 4.Future(各种Future) 5.Fork/Join框架 6.volatile 7.CAS(原子操作) 8.AQS(并发同 ...
- 如何避免Java中的回调“地狱”
来自:锅外的大佬 本篇文章将简要介绍进行同步远程调用所涉及的代码类型.然后,我们将演示非阻塞 IO 中的分层如何高效使用资源(尤其是线程),引入了称为回调地狱带来的复杂性以及基于反应流方法如何简化编程 ...
- CompletableFuture 实现异步计算
在Markdown的语法中,<u>下划线</u>中的文字会被解析器加上下划线,为了不影响阅读,本文中JDK文档涉及到<U>都会替换为<N>,请各位注意. ...
- 将 5 万行 Java 代码移植到 Go 学到的经验
原文地址: Lessons learned porting 50k loc from Java to Go 原文作者:Krzysztof Kowalczyk 译文出处: https://blog.ko ...
最新文章
- python安装包-安装 Python 模块
- 一段javascript告警回放代码
- js 获取td高度_JS或jQuery获取宽高度
- Docker最全教程之树莓派和Docker(十六)
- Hibernate READ_ONLY CacheConcurrencyStrategy如何工作
- java join()用法_四种联系(join)的区别及用法
- 关于Jeecg互联网化dubbo改造方案(下)
- 使用Notepad++作为Latex编辑器
- vc6开发一个抓包软件_开发一个软件要多少钱?app软件开发的费用
- Android 功耗(5)----功耗调试
- linux下双击sh文件夹,Linux系统下如何运行.sh文件的实现
- Ambari ambari 集群及组件
- C# winform以阅览模式打开PPT,并控制PPT上下页,轮播
- 使用PING判断TCP/IP故障
- js中eval的用法
- (day 26 - 广度优先搜索 )剑指 Offer 32 - III. 从上到下打印二叉树 III
- 5. 块定义(AttributeDefinition)
- Locust1.x 的监控平台——boomer
- 网页游戏mysql修改_大天使之剑奇迹网页游戏 一键服务端+架设教程+修改方法
- 【STM32】RTC实时时钟概述、寄存器、库函数(RTC一般步骤)
热门文章
- java future接口_java Future 接口介绍
- java皮肤库的框架_VC 添加皮肤库
- java程序设计简明教程张晓龙_Java网络编程简明教程
- buck变换器设计matlab_[Fundamental of Power Electronics]-PART I-6.变换器电路-6.2 变换器简单罗列 - Yangswear...
- html选择第一个clss,css3如何选择第一个子元素?
- python执行shell脚本报错_在python中执行shell命令:字符串错误
- 漳州职业技术学院计算机学费多少钱,漳州职业技术学院单招2021年学费多少
- php镂空窗,木窗镂空的雕刻象征着什么?黑色在彝族人民心中有何寓意?陆川猪为何是著名“陆川三宝”之一?...
- 移远ec20驱动_移远通信Cat 1产品天团迎来新成员,引爆中速连接市场
- android 触摸屏 不支持 配置,Android触摸屏配置调试