http://colobu.com/2016/02/29/Java-CompletableFuture/

http://www.deadcoderising.com/java8-writing-asynchronous-code-with-completablefuture/

https://www.jianshu.com/p/558b090ae4bb,CompletableFuture API详解

Java8 lamda

http://ifeve.com/lambda/

lamda可以认为是匿名函数,用过scala的都很熟悉

Java8 supplier

http://www.byteslounge.com/tutorials/java-8-consumer-and-supplier

supplier,

Suppliers represent a function that accepts no arguments and produce a result of some arbitrary type.

A Future represents the pending result of an asynchronous computation. It offers a method — get — that returns the result of the computation when it's done.

The problem is that a call to get is blocking until the computation is done. This is quite restrictive and can quickly make the asynchronous computation pointless.

传统的Future,提供异步计算的可能性

不过Future的结果需要用get去获取,这个过程是block的或者轮询,所以这样又限制了异步

Beside implementing the Future interface, CompletableFuture also implements the CompletionStage interface.

A CompletionStage is a promise. It promises that the computation eventually will be done.

The great thing about the CompletionStage is that it offers a vast selection of methods that let you attach callbacks that will be executed on completion.

This way we can build systems in a non-blocking fashion.

所以我们需要CompletableFuture,除了future接口,还实现CompletionStage接口

CompletionStage的作用是,提供给你很多方法,让你可以attach各种callbacks用于future执行完成后的followup

这样我们更容易build non-blocking的系统

例子,

Let's start with the absolute basics — creating a simple asynchronous computation.

CompletableFuture.supplyAsync(this::sendMsg);

It's as easy as that.

supplyAsync takes a Supplier containing the code we want to execute asynchronously — in our case the sendMsgmethod.

异步执行supplier的逻辑,什么是supplier见上面

If you've worked a bit with Futures in the past, you may wonder where the Executor went. If you want to, you can still define it as a second argument. However, if you leave it out it will be submitted to the ForkJoinPool.commonPool().

ForkJoinPool.commonPool

Java 8为ForkJoinPool添加了一个通用线程池,这个线程池用来处理那些没有被显式提交到任何线程池的任务。它是ForkJoinPool类型上的一个静态元素,它拥有的默认线程数量等于运行计算机上的处理器数量

commonPool可以理解为由JVM管理的一个通用线程池,谁都可以用

加上callback

In the first example, we simply sent a message asynchronously by executing sendMsg in its own thread.

Now let's add a callback where we notify about how the sending of the message went.

CompletableFuture.supplyAsync(this::sendMsg)
.thenAccept(this::notify);

thenAccept is one of many ways to add a callback. It takes a Consumer — in our case notify — which handles the result of the preceding computation when it's done.

thenAccept是加callback的一种方式,当然有很多种加callback的方式;

这里thenAccept是一种Consumer function,consumer即接受参数没有返回的一种function

在这里notify会作为consumer会接收sendMsg是输出作为输入来继续处理

加上多个callbacks

If you want to continue passing values from one callback to another, thenAccept won't cut it since Consumer doesn't return anything.

To keep passing values, you can simply use thenApply instead.

上面说了thenAccept是一种Consumer,是不会有返回值的,所以如果要级联多个callback,需要用thenApply,它是既有输入参数,又有返回值

thenApply takes a Function which accepts a value, but also return one.

To see how this works, let's extend our previous example by first finding a receiver.

    CompletableFuture.supplyAsync(this::findReceiver)
.thenApply(this::sendMsg)
.thenAccept(this::notify);

Now the asynchronous task will first find a receiver, then send a message to the receiver before it passes the result on to the last callback to notify.

thenCompose

Until now, sendMsg has been a normal blocking function. Let's now assume that we got a sendMsgAsync method that returns a CompletionStage.

If we kept using thenApply to compose the example above, we would end up with nested CompletionStages.

CompletableFuture.supplyAsync(this::findReceiver)
.thenApply(this::sendMsgAsync); // Returns type CompletionStage<CompletionStage<String>>

这个例子会出现多个异步的嵌套,

所以这里用thenCompose,去除掉嵌套

CompletableFuture.supplyAsync(this::findReceiver)
.thenCompose(this::sendMsgAsync); // Returns type CompletionStage<String>

异步的执行callback

Until now all our callbacks have been executed on the same thread as their predecessor.

If you want to, you can submit the callback to the ForkJoinPool.commonPool() independently instead of using the same thread as the predecessor. This is done by using the async suffix version of the methods CompletionStage offers.

我们也可以异步的执行callback,

CompletableFuture<String> receiver
= CompletableFuture.supplyAsync(this::findReceiver); receiver.thenApply(this::sendMsg);
receiver.thenApply(this::sendOtherMsg);

这个例子中,两次的消息发送都是在当前线程中完成的,我们也可以给加上async前缀,让他们异步的执行,

CompletableFuture<String> receiver
= CompletableFuture.supplyAsync(this::findReceiver); receiver.thenApplyAsync(this::sendMsg);
receiver.thenApplyAsync(this::sendMsg);

异常处理

CompletableFuture.supplyAsync(this::failingMsg)
.exceptionally(ex -> new Result(Status.FAILED))
.thenAccept(this::notify);

exceptionally gives us a chance to recover by taking an alternative function that will be executed if preceding calculation fails with an exception.

This way succeeding callbacks can continue with the alternative result as input.

If you need more flexibility, check out whenComplete and handle for more ways of handling errors.

thenCombine

thenCombine allows us to register a BiFunction callback depending on the result of two CompletionStages.

CompletableFuture<String> to =
CompletableFuture.supplyAsync(this::findReceiver); CompletableFuture<String> text =
CompletableFuture.supplyAsync(this::createContent); to.thenCombine(text, this::sendMsg);

上面的是both的case

下面的是either的case

Let’s say you have two sources of finding a receiver. You’ll ask both, but will be happy with the first one returning with a result.

CompletableFuture<String> firstSource =
CompletableFuture.supplyAsync(this::findByFirstSource); CompletableFuture<String> secondSource =
CompletableFuture.supplyAsync(this::findBySecondSource); firstSource.acceptEither(secondSource, this::sendMsg);

完成时回调

T get() throws InterruptedException, ExecutionException
T join()
这两个方法都是从CompletableFuture里面取值的,调用时会阻塞当前线程。可以很容易看出join没有抛出非运行时异常,不过它会抛出2个运行时异常:
当这个任务被取消时会抛出CancellationException;当任务执行时抛出异常时,会抛出CompletionException。
当我们需要从任务中拿值时,推荐join()方法。

boolean complete(T)
如果任务未完成,则在拿取返回值时返回T。如果此次调用将CompletableFuture转化为“完成”状态,则返回true,否则返回false。
通过get()或join()拿到的是类型T的值,则返回true,否则返回false。
whenComplete(BiConsumer<T, Throwable>)
该方法有点像thenAccept(Consumer<T>) ,只不过增加了一个异常处理的功能。
传入的参数类似于handle,如果上一个任务出了异常,则传入的T类型为null,Throwable为抛出的异常;
如果正常运行,则T类型为之前任务运行后的返回值,Throwable为null


Java8 CompletableFuture的更多相关文章

  1. Java8 CompletableFuture 编程

    一.简介  所谓异步调用其实就是实现一个无需等待被调用函数的返回值而让操作继续运行的方法.在 Java 语言中,简单的讲就是另启一个线程来完成调用中的部分计算,使调用继续运行或返回,而不需要等待计算结 ...

  2. Java8 CompletableFuture组合式的编程(笔记)

    * 实现异步API public double getPrice(String product) { return calculatePrice(product); } /** * 同步计算商品价格的 ...

  3. Atitit eclipse新特性总结3.1---4.4  4.5

    Atititeclipse新特性总结3.1---4.4  4.5 1. Eclipse 4.4 Luna正式发布了.1 1.1. 新版本的Eclipse默认对Java8提供支持1 1.2. 内存分析器 ...

  4. JAVA8给我带了什么——Optional和CompletableFuture

    不管是JAVA,还是.NET.我们常常会看到空异常(NullPointerException).这种异常都是在运行的过程中出现.往往是变量是一个null值.但是你引用这个变量的后继字段或是方法.所以我 ...

  5. Java8 中增强 Future:CompletableFuture

    增强的 Future:CompletableFuture CompletableFuture(它实现了 Future 接口) 和 Future 一样,可以作为函数调用的契约.当你向它请求获得结果,如果 ...

  6. Java8 增强的Future:CompletableFuture(笔记)

    CompletableFuture是Java8新增的一个超大型工具类,为什么说她大呢?因为一方面它实现了Future接口,更重要的是,它实现了CompletionStage接口.这个接口也是Java8 ...

  7. Java8系列 (七) CompletableFuture异步编程

    概述 Java8之前用 Future 处理异步请求, 当你需要获取任务结果时, 通常的做法是调用  get(long timeout, TimeUnit unit) 此方法会阻塞当前的线程, 如果任务 ...

  8. Java8新特性: CompletableFuture详解

    CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步回调.流式处理.多个Future组合处理的能力,使Java在处理多任务的 ...

  9. Java8 异步编排类CompletableFuture

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. https://www.cnblogs.com/shijiaqi1066/p/8758206 ...

随机推荐

  1. Fluent动网格【7】:网格节点运动

    在动网格中,对于那些既包含了运动也包含了变形的区域,可以通过UDF来指定区域中每一个节点的位置.这给了用户最大的自由度来指定网格的运动.在其他的动网格技术中(如重叠网格)则很难做到这一点.定义网格节点 ...

  2. 【Java】分布式RPC通信框架Apache Thrift 使用总结

    简介 Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于th ...

  3. 不8000就业,不还实习费的AICODER全栈实习二期开始报名

    4月17日是个伟大的日子,AICODER全栈实习一期班,正式开始!伙伴们已经撸起袖子加油干了. 二期班开始报名 二期班定于5月17日开班,从二期班开始,实习费用调整如下: 三个月模式实习费,调整为12 ...

  4. mysql解除死锁状态

    方案一: 1.查看是否有锁表 show OPEN TABLES ; 2.查询进程(如果你有SUPER权限,你可以看到所有线程.否则,只能看到你自己的线程) show processlist; 3.杀死 ...

  5. oracle函数详解-转

    1.SQL 语句基础 下面给出SQL语句的基本介绍. 1.1.SQL语句所用符号 操作符 用途 例子 + - 表示正数或负数,正数可省去 + -1234.56 + 将两个数或表达式进行相加 A=c+b ...

  6. JPA 不生成外键

    在用jpa这种orm框架时,有时我们实体对象存在关联关系,但实际的业务场景可能不需要用jpa来控制数据库创建数据表之间的关联约束,这时我们就需要消除掉数据库表与表之间的外键关联.但jpa在处理建立外键 ...

  7. json转 PostMan bulk Edit application/x-www-form-urlencoded 需要的格式

    {?\n\s*"([^"]+)"\s*:\s*"?([^,"]+)"?\s*,?}? $1:$2\n PostMan需要的格式. json转 ...

  8. 服务器部署多个tomcat(Address already in use: JVM_Bind)

    一.修改startup.bat **多个Tomcat同时运行时.不要设置 catalina_home catalina_base classes 环境变量, 修改setclasspath.bat (| ...

  9. PHP最全笔记(五)(值得收藏,不时翻看一下)

    // 删除 方法1:将其值设置为空字符串 setcookie('user[name]', ''); 方法2:将目标cookie设为“已过期”状态. //将cookie的生存时间设置为过期,则生存期限与 ...

  10. [Algorithm] Polynomial and FFT

    排序:nlogn 二分查找:logn <-- 利用单调性,查n次,每次logn Multiply the following pairs of polynomials using at most ...