java中的异步处理和Feature接口(一)
背景介绍
想象这样一个场景:你可能希望为你的法国客户提供指定主题的热点报道。为实现这一功能,你需要向 谷歌或者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示例:
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
java中的异步处理和Feature接口(一)的更多相关文章
- Java中的集合(十三) 实现Map接口的Hashtable
Java中的集合(十三) 实现Map接口的Hashtable 一.Hashtable简介 和HashMap一样,Hashtable采用“拉链法”实现一个哈希表,它存储的内容是键值对(key-value ...
- Java中的集合(十一) 实现Map接口的TreeMap
Java中的集合(十一) 实现Map接口的TreeMap 一.TreeMap简介(基于JDK1.8) TreeMap是基于红黑树数据结构,是一个key-value的有序集合,该映射根据其键的自然顺序进 ...
- Java中的异步通知
在我们的日常开发中,经常会遇到这样的问题--"我让你做一件事情,但是你做得很慢,并不能够立马返回给我结果,害我一直在那儿等着你给我返回结果,什么都做不了". 程序是自上而下顺序执行 ...
- java 中的异步回调
异步回调,本来在c#中是一件极为简单和优雅的事情,想不到在java的世界里,却如此烦琐,先看下类图: 先定义了一个CallBackTask,做为外层的面子工程,其主要工作为start 开始一个异步操作 ...
- Java学习--java中的集合框架、Collection接口、list接口
与数组相比:1.数组的长度固定,而集合的长度可变2.数组只能通过下表访问元素,类型固定,而有的集合可以通过任意类型查找所映射的具体对象 java集合框架:collection(list序列,queue ...
- java中同步异步阻塞和非阻塞的区别
同步 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回. 按照这个定义,其实绝大多数函数都是同步调用(例如sin, isdigit等).但是一般而言,我们在说同步.异步的时候,特 ...
- java中并不是任意多个接口都可以实现多实现
interface A{ public abstract void show(); } interface B{ public abstract int show(); } public class ...
- Java中抽象类和接口的用法和区别
一.抽象类 1.抽象类 包含一个抽象方法的类就是抽象类 2.抽象方法 声明而未被实现的方法,抽象方法必须使用abstract关键词字声明 public abstract class People { ...
- Java中的集合(六)继承Collection的Set接口
Java中的集合(六)继承Collection的Set接口 一.Set接口的简介 Set接口和List接口都是继承自Collection接口,它与Collection接口中功能基本一致,并没有对Col ...
随机推荐
- java入门学习总结_03
1.键盘录入 2.分支结构 键盘录入 概述 1.键盘录入:在程序运行的过程中,可以让用户录入一些数据,存储在内存的变量中,在后续的程序运行过程中,可以使用这些数据. 2.步骤: 第一步:导包,在类声明 ...
- Python概要介绍
Python的由来 Python的创始人(Guido Van Rossum)吉多·范罗苏姆——龟叔,1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,做 ...
- 查看python和NumPy版本和安装路径
记录查看Python和NumPy版本以及路径的几条命令 # 查看Python版本及路径 python -V python -c "import sys;print(sys.executabl ...
- 深度解析Graph Embedding
Graph Embedding是推荐系统.计算广告领域最近非常流行的做法,是从word2vec等一路发展而来的Embedding技术的最新延伸:并且已经有很多大厂将Graph Embedding应用于 ...
- hibernate的详解
一,环境的搭建 1)创建maven项目 2)导入依赖的jar包.pom.xml和创建实体类User <?xml version="1.0" encoding="UT ...
- Css案例整理
1.实现两个div并排显示 案例:checkbox的标题和内容需要并排显示,checkbox竖向排列 <head> <style type="text/css"& ...
- js中in关键字的使用方法
1.for...in 对数组或对象的循环/迭代操作 对于数组循环出来的是数组元素:对于对象循环出来的是对象属性 2.判断对象是否是数组/对象的元素/属性 格式:(变量 in 对象) 当‘对象’是数组时 ...
- 2019HDU多校第四场 Just an Old Puzzle ——八数码有解条件
理论基础 轮换与对换 概念:把 $S$ 中的元素 $i_1$ 变成 $i_2$,$i_2$ 变成 $i_3$ ... $i_k$ 又变成 $i_1$,并使 $S$ 中的其余元素保持不变的置换称为循环, ...
- 25、自动装配-@Profile根据环境注册bean
25.自动装配-@Profile根据环境注册bean 指定组件在哪个环境的情况下才能被注册到容器中 加了环境标识的,只有这个环境被激活才能注册到组件中 默认是default环境 写在类上,整个配置类的 ...
- TFS命令行
tfs命令工具: https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/9s5ae285 ...