java8completablefuture详解剖析

上传人:今*** 文档编号:105948711 上传时间:2019-10-14 格式:DOC 页数:11 大小:61.50KB
返回 下载 相关 举报
java8completablefuture详解剖析_第1页
第1页 / 共11页
java8completablefuture详解剖析_第2页
第2页 / 共11页
java8completablefuture详解剖析_第3页
第3页 / 共11页
java8completablefuture详解剖析_第4页
第4页 / 共11页
java8completablefuture详解剖析_第5页
第5页 / 共11页
点击查看更多>>
资源描述

《java8completablefuture详解剖析》由会员分享,可在线阅读,更多相关《java8completablefuture详解剖析(11页珍藏版)》请在金锄头文库上搜索。

1、Java8 CompletableFuture详解Java 8来了,是时候学一下新的东西了。Java 7和Java 6只不过是稍作修改的版本,而Java 8将会发生重大的改进。或许是Java 8太大了吧?今天我会给你彻底地解释JDK 8中的新的抽象 CompletableFuture。众所周知,Java 8不到一年就会发布,因此这篇文章是基于JDK 8 build 88 with lambda support的。CompletableFuture extends Future提供了方法,一元操作符和促进异步性以及事件驱动编程模型,它并不止步于旧版本的Java中。如果你打开JavaDoc of

2、CompletableFuture你一定会感到震惊。大约有五十种方法(!),而且它们中的一些非常有意思而且不好理解,例如:复制代码 代码如下:public CompletableFuture thenCombineAsync( CompletableFuture other, BiFunction fn, Executor executor)不必担心,继续读下去。CompletableFuture收集了所有ListenableFuture in Guava 和 SettableFuture的特征。此外,内置的lambda表达式使它更接近于Scala/Akka futures。这听起来好得令人难

3、以置信,但是请继续读下去。CompletableFuture有两个主要的方面优于ol中的Future 异步回调/转换,这能使得从任何时刻的任何线程都可以设置CompletableFuture的值。 一、提取、修改包装的值 通常futures代表其它线程中运行的代码,但事实并非总是如此。有时你想要创造一个Future来表示你知道将会发生什么,例如JMS message arrival。所以你有Future但是未来并没有潜在的异步工作。你只是想在未来JMS消息到达时简单地完成(解决),这是由一个事件驱动的。在这种情况下,你可以简单地创建CompletableFuture来返还给你的客户端,只要你认

4、为你的结果是可用的,仅仅通过complete()就能解锁所有等待Future的客户端。 首先你可以简单地创建新的CompletableFuture并且给你的客户端:复制代码 代码如下:public CompletableFuture ask() final CompletableFuture future = new CompletableFuture(); /. return future;注意这个future和Callable没有任何联系,没有线程池也不是异步工作。如果现在客户端代码调用ask().get()它将永远阻塞。如果寄存器完成回调,它们就永远不会生效了。所以关键是什么?现在你可以

5、说:复制代码 代码如下:plete(42)此时此刻所有客户端Future.get()将得到字符串的结果,同时完成回调以后将会立即生效。当你想代表Future的任务时是非常方便的,而且没有必要去计算一些执行线程的任务上。CompletableFplete()只能调用一次,后续调用将被忽略。但也有一个后门叫做CompletableFuture.obtrudeValue()覆盖一个新Future之前的价值,请小心使用。 有时你想要看到信号发生故障的情况,如你所知Future对象可以处理它所包含的结果或异常。如果你想进一步传递一些异常,可以用CompletableFpleteExceptionally

6、(ex) (或者用obtrudeException(ex)这样更强大的方法覆盖前面的异常)。 completeExceptionally()也能解锁所有等待的客户端,但这一次从get()抛出异常。说到get(),也有CompletableFuture.join()方法在错误处理方面有着细微的变动。但总体上,它们都是一样的。最后也有CompletableFuture.getNow(valueIfAbsent)方法没有阻塞但是如果Future还没完成将返回默认值,这使得当构建那种我们不想等太久的健壮系统时非常有用。 最后static的方法是用completedFuture(value)来返回已经完

7、成Future的对象,当测试或者写一些适配器层时可能非常有用。 二、创造和获取CompletableFuture 好了,那么手动地创建CompletableFuture是我们唯一的选择吗?不一定。就像一般的Futures,我们可以关联存在的任务,同时CompletableFuture使用工厂方法:复制代码 代码如下:static CompletableFuture supplyAsync(Supplier supplier);static CompletableFuture supplyAsync(Supplier supplier, Executor executor);static Com

8、pletableFuture runAsync(Runnable runnable);static CompletableFuture runAsync(Runnable runnable, Executor executor); 无参方法Executor是以Async结尾同时将会使用ForkJoinPmonPool()(全局的,在JDK8中介绍的通用池),这适用于CompletableFuture类中的大多数的方法。runAsync()易于理解,注意它需要Runnable,因此它返回CompletableFuture作为Runnable不返回任何值。如果你需要处理异步操作并返回结果,使用Su

9、pplier:复制代码 代码如下:final CompletableFuture future = CompletableFuture.supplyAsync(new Supplier() Override public String get() /.long running. return 42; , executor); 但是别忘了,Java 8里面还有lambdas表达式呢!复制代码 代码如下:finalCompletableFuture future = CompletableFuture.supplyAsync() - /.long running. return 42;, exec

10、utor); 或者: 复制代码 代码如下:final CompletableFuture future = CompletableFuture.supplyAsync() - longRunningTask(params), executor); 虽然这篇文章不是关于Lambda的,但是我会相当频繁地使用lambda表达式。 三、转换和作用于CompletableFuture(thenApply) 我说过CompletableFuture优于Future但是你还不知道为什么吗?简单说,因为CompletableFuture是一个原子也是一个因子。我说的这句话没什么帮助吗?Scala和JavaS

11、cript都允许future完成时允许注册异步回调,直到它准备好我们才要等待和阻止它。我们可以简单地说:运行这个函数时就出现了结果。此外,我们可以叠加这些功能,把多个future组合在一起等。例如如果我们从String转为Integer,我们可以转为在不关联的前提下从CompletableFuture到 CompletableFutureInteger。这是通过thenApply()的方法:复制代码 代码如下: CompletableFuture thenApply(Function fn); CompletableFuture thenApplyAsync(Function fn); Com

12、pletableFuture thenApplyAsync(Function fn, Executor executor);如前所述.Async版本提供对CompletableFuture的大多数操作,因此我将在后面的部分中跳过它们。记住,第一个方法将在future完成的相同线程中调用该方法,而剩下的两个将在不同的线程池中异步地调用它。让我们来看看thenApply()的工作流程:CompletableFuture f1 = /.CompletableFuture f2 = f1.thenApply(Integer:parseInt);CompletableFuture f3 = f2.the

13、nApply(r - r * r * Math.PI); 或在一个声明中:复制代码 代码如下:CompletableFuture f3 = f1.thenApply(Integer:parseInt).thenApply(r - r * r * Math.PI); 这里,你会看到一个序列的转换,从String到Integer再到Double。但最重要的是,这些转换既不立即执行也不停止。这些转换既不立即执行也不停止。他们只是记得,当原始f1完成他们所执行的程序。如果某些转换非常耗时,你可以提供你自己的Executor来异步地运行他们。注意,此操作相当于Scala中的一元map。 四、运行完成的代码(thenAccept/thenRun)复制代码 代码如下:CompletableFuture thenAccept(Consumer block);CompletableFuture thenRun(Runnable action); 在future的管道里有两种典型的“最终”阶段方法。他们在你使用future的值的时候做好准备,当 thenAccept()提供最终的值时,thenRun执行 Runnable,这甚至没有方法去计算值。例如:复制代码 代码如下:future.thenAcceptAsync(d

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号