背景介绍
想象这样一个场景:你可能但愿为你的法国客户提供指定主题的热点报道。为实现这一功能,你须要向 谷歌或者Twitter的API请求全部语言中针对该主题最热门的评论,可能还须要依据你的内部算法 对它们的相关性进行排序。以后,你可能还须要使用谷歌的翻译服务把它们翻译成法语,甚至 利用谷歌地图服务定位出评论做者的位置信息,最终将全部这些信息汇集起来,呈如今你的网站上。算法
典型的“混聚”式应用数据库
在这种“混聚”应用式的应用中,咱们的应用可能会有如下两种需求:编程
因为咱们调用的许多都是外部提供的接口,极有可能出现因为某些外部网络服务发生响应慢的状况。在这种状况下,咱们可能但愿依旧能为用户提供部分信息,好比提供带问号标记的通用地图,以文本的方式显示信息,而不是呆呆地显示一片空白屏幕,直到地图服务器返回结果或者超时退出。服务器
要实现相似的服务,你须要与互联网上的多个Web服务通讯。但是,你并不但愿由于等待某 些服务的响应,阻塞应用程序的运行,浪费数十亿宝贵的CPU时钟周期。好比,不要由于等待 Facebook的数据,暂停对来自Twitter的数据处理。网络
以上两种场景体现了多任务程序设计的另外一面。若是你的主要目标是在同一个CPU上执 行几个松耦合的任务,充分利用CPU的核,让其足够忙碌,从而最大化程序的吞吐量,那么你其实真正想作的是避免由于等待远程服务的返回,或者对数据库的查询,而阻塞线程的执行, 浪费宝贵的计算资源,由于这种等待的时间极可能至关长。这时就须要用到异步处理,在Java 5中提供的Future接口和在Java 8 中的新版实现CompletableFuture,就是处理这种状况的利器。并发
Feature接口
Future接口在Java 5中被引入,设计初衷是对未来某个时刻会发生的结果进行建模。它建模 了一种异步计算,返回一个执行运算结果的引用,当运算结束后,这个引用被返回给调用方。在 Future中触发那些潜在耗时的操做把调用线程解放出来,让它能继续执行其余有价值的工做, 再也不须要呆呆等待耗时的操做完成。异步
Feature接口和Tread的区别
Future的优势是它比 更底层的Thread更易用。要使用Future,一般你只须要将耗时的操做封装在一个Callable对 象中,再将它提交给ExecutorService,就万事大吉了。网站
Feature接口示例
下面是一个Feature的demo示例:.net
public void testFeature() {
//建立Executor- Service,通 过它你能够 向线程池提 交任务
ExecutorService executor = Executors.newCachedThreadPool();
//向Executor- Service提交一个 Callable对象
final Future<Double> futureRate = executor.submit(new Callable<Double>() {
public Double call() {
//以异步方式在新的线程中执行耗时的操做
return doSomeLongComputation();
}
});
//异步操做进行的同时你能够作其余的事情
doSomethingElse();线程
try {
//获取异步操做的结果,若是最终被阻塞,没法获得结果,那么在最多等待1秒钟以后退出
Double result = future.get(1, TimeUnit.SECONDS);
} catch (ExecutionException e) {
// 计算抛出一个异常
e.printStackTrace();
} catch (InterruptedException ie) { // 当前线程在等待过程当中被中断
} catch (TimeoutException te) { // 在Future对象完成以前超过已过时
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
使用Future以异步方式执行长时间的操做
如上图所示,这种编程方式让你的线程能够在ExecutorService以并发方式调 用另外一个线程执行耗时操做的同时,去执行一些其余的任务。接着,若是你已经运行到没有异步 操做的结果就没法继续任何有意义的工做时,能够调用它的get方法去获取操做的结果。若是操 做已经完成,该方法会马上返回操做的结果,不然它会阻塞你的线程,直到操做完成,返回相应 的结果。若是该长时间运行的操做永远不返回了会怎样?为了处理这种可能性,虽然Future提供了一个无需任何参数的get方法,咱们仍是推荐你们使用重 载版本的get方法,它接受一个超时的参数,经过它,你能够定义你的线程等待Future结果的最 长时间,从而无需永无止境的等待下去。
Feature接口的局限性
虽然Feature接口提供了方法来检测异步计算是否已经结束(使用 isDone方法),等待异步操做结束,以及获取计算的结果。可是这些特性还不足以让你编写简洁的并发代码。
咱们可能还须要更多的特性来帮助咱们写出更好异步代码,如:
将两个异步计算合并为一个——这两个异步计算之间相互独立,同时第二个又依赖于第 一个的结果。
等待Future集合中的全部任务都完成。
仅等待Future集合中最快结束的任务完成(有可能由于它们试图经过不一样的方式计算同一个值),并返回它的结果。
经过编程方式完成一个Future任务的执行(即以手工设定异步操做结果的方式)。
应对Future的完成事件(即当Future的完成事件发生时会收到通知,并能使用Future
计算的结果进行下一步的操做,不仅是简单地阻塞等待操做的结果)。
下一节咱们将介绍新的CompletableFuture类(它实现了Future接口)如何利用Java 8 的新特性以更直观的方式将上述需求都变为可能。————————————————版权声明:本文为CSDN博主「栋先生」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接及本声明。原文连接:https://blog.csdn.net/wangdong5678999/article/details/81837387