Google Guava –期货

这篇文章是我在Google Guava上的系列文章的延续,这次涵盖了Future。 Futures类是用于使用Future / ListenableFuture接口的静态实用程序方法的集合。 Future是提交给ExecutorService的异步任务(可运行或可调用)的句柄。 Future界面提供以下方法:获取任务的结果,检查任务是否完成或取消任务。 ListenableFuture接口扩展了Future接口,并添加了将完成侦听器设置为在任务完成后运行的功能。 要创建ListenableFuture,您首先需要装饰一个ExecutorService实例,如下所示:

ExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());

现在所有提交的Callables / Runnables将返回一个ListenableFuture。 MoreExecutors可以在com.google.common.util.concurrent包中找到。 ListenableFutures在覆盖以前的帖子 。 期货中有太多方法无法有效地涵盖在一篇文章中,所以我只涉及:链,转换,allAsList和successAsList。 在这篇文章中,我将交替使用Futures和ListenableFutures。

链方法返回一个ListenableFuture,其值是通过从输入Future中获取结果并将其作为参数应用到Function对象来计算的, Function对象又返回另一个ListenableFuture。 让我们看一个代码示例并逐步执行:

ListenableFuture<List<String>> indexSearch = luceneSearcher.searchAsync('firstName:martin');Function<List<String>, ListenableFuture<List<Person>>> queryFunction = new Function<List<String>, ListenableFuture<List<Person>>>() {@Overridepublic ListenableFuture<List<Person>> apply(final List<String> ids) {return dataService.getPersonsByIdAsync(ids);}};ListenableFuture<List<Person>> results = Futures.chain(indexSearch, queryFunction,executorService);
  1. 第1行正在使用Lucene执行异步搜索,并将返回一个ID列表,这些ID代表存储在数据库中的人员记录的主键。 (我创建了一个小索引,其中存储在Lucene中的唯一数据是id的数据,其余数据仅被索引了)。
  2. 第4 – 11行正在构建功能对象,其中apply方法将使用搜索未来的结果作为输入。 apply返回的将来是对dataService对象的调用的结果。
  3. 第12行是从链调用返回的未来。 一旦输入将来完成,将使用executorService运行该功能。

为了更加清楚,这是searchAsync和getPersonsByIdAsync方法的作用。 在前面的代码示例中,这些方法调用分别来自第2行和第8行:

public ListenableFuture<List<String>> searchAsync(final String query)  {return executorService.submit(new Callable<List<String>>() {@Overridepublic List<String> call() throws Exception {return search(query);}});}public ListenableFuture<List<Person>> getPersonsByIdAsync(final List<String> ids) {return executorService.submit(new Callable<List<Person>>() {@Overridepublic List<Person> call() throws Exception {return getPersonsById(ids);}});}

chain方法具有两个签名:

  1. 链(ListentableFuture,函数)
  2. 链(ListenableFuture,函数,ExecutorService)

在确定使用哪种方法时,有几点要考虑。
如果通过调用时间链完成了输入将来,则所提供的函数将在调用线程中立即执行。 此外,如果未提供执行程序,则使用MoreExecutors.sameThreadExecutor。 MoreExecutors.sameThreadExecutor(顾名思义)位于ThreadPoolExecutor.CallerRunsPolicy之后,这意味着提交的任务在与执行/提交相同的线程中运行。

转变

转换方法类似于链式方法,因为它以Future和Function对象作为参数。 不同之处在于,不返回ListenableFuture,仅返回将给定功能应用于输入future的结果。 考虑以下:

List<String> ids = ....
ListenableFuture<List<Map<String, String>>> dbRecords =   dataService.getPersonDataByIdAsync(ids);Function<List<Map<String, String>>,List<Person>> transformDbResults = new Function<List<String>, List<Person>>() {@Overridepublic List<Person> apply(List<Map<String, String>> personMapList) {List<Person> personObjList = new ArrayList<Person>();for(Map<String,String> personDataMap : personMapList){personObjList.add(new Person(personDataMap);} return personObjList;}};ListenableFuture<List<Person>> transformedResults = Futures.transform(dbRecords, transformDbResults, executorService);
  1. 在第2行上,执行异步数据库查找
  2. 在第4行上,正在创建一个函数对象,但是在第8行上,请注意返回类型为List <Person>

transform方法具有与chain相同的重载方法调用,但有相同的警告。

AllAsList

allAsList方法将采用任意数量的ListenableFutures作为变量或以Iterator <ListenableFuture>的形式。 返回一个ListenableFuture,其值是所有输入结果的列表。 列表中返回的值与原始列表的顺序相同。 如果任何输入值被取消或失败,则返回的ListenableFuture也将被取消或失败。 从allAsList调用取消返回的future不会传播到列表中提交的任何原始任务。

ListenableFuture<List<Person>> lf1 = getPersonsByFirstNameFuture('martin');
ListenableFuture<List<Person>> lf2 = getPersonsByFirstNameFuture('bob');
ListenableFuture<List<List<Person>>> lfResults = Futures.allAsList(lf1, lf2);
//assume lf1 failed
List<List<Person>> personLists = lfResults.get() //call results in exception


成功名单

successAsList方法与allAsList非常相似,但是更加宽容。 就像allAsList一样,successAsList返回结果列表的顺序与输入列表的顺序相同,但是如果任何输入失败或被取消,则列表中的相应值将为null。 取消返回的将来也不会取消任何原始输入。

ListenableFuture<List<Person>> lf1 = getPersonsByFirstNameFuture('martin');
ListenableFuture<List<Person>> lf2 = getPersonsByFirstNameFuture('bob');
ListenableFuture<List<List<Person>>> lfResults = Futures.successfulAsList(lf1, lf2);
//assume lf1 failed
List<List<Person>> personLists = lfResults.get();
List<Person> listOne = personLists.get(0) //listOne is null
List<Person> listTwo = personLists.get(1) //listTwo, not null


结论

希望这有助于发现Google Guava的Futures类中包含的有用性。 我创建了一个单元测试,以显示本文中描述的方法的示例用法。 由于有大量支持代码,因此我在gihub上创建了一个项目guava-blog 。 该项目还将包含我以前在Guava上发表的文章( Monitor , ListenableFuture )的源代码。 一如既往地欢迎提出意见和建议。

资源资源

  • 番石榴项目首页
  • 期货API
  • 博客系列的源代码


参考资料: Google Guava – JCG合作伙伴 Bill Bejeck的期货,来自Random Thoughts On Coding博客。

翻译自: https://www.javacodegeeks.com/2012/11/google-guava-futures.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370721.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iptables 配置后连接不上数据库_Linux服务器配置-VSFTP服务配置(三)

上文&#xff1a;Linux服务器配置-VSFTP服务配置(二)一、vsftpd服务防火墙配置1、主动(POST)模式 FTP 防火墙配置CentOS6 系统 iptables 的配置iptables -t filter --line-number -nL INPUT#显示现有防火墙规则&#xff0c;查看是否开启20、21号端口。iptables -t filter -I IN…

下标索引必须为正整数类型或逻辑类型_Python3 基本数据类型

Python中的变量不需要声明。每个变量在使用前都必须赋值&#xff0c;变量赋值以后该变量才会被创建。在Python中&#xff0c;变量就是变量&#xff0c;它没有类型&#xff0c;我们所说的"类型"是变量所指的内存中对象的类型。Python 3中有六个标准的数据类型&#xf…

noip模拟赛 写代码

分析&#xff1a;这其实就是括号匹配题&#xff0c;一眼贪心题&#xff0c;不过一开始贪错了&#xff0c;以为([)]是合法的......其实括号之间不能嵌套. 一开始的想法是尽量往左边填左括号&#xff0c;因为每种括号的数量都确定了&#xff0c;那么左括号和右括号的数量也就确定…

[CF797C] Minimal string(贪心,栈)

题目链接&#xff1a;http://codeforces.com/contest/797/problem/C 题意&#xff1a;给个字符串&#xff0c;求字典序最小的出栈顺序。 一开始想用优先队列记录全局最小的字符&#xff0c;然后每次入栈的时候检查当前字符是不是最小的&#xff0c;如果是那么同时pop。这样做的…

让我们紧缩大数据

作为开发人员&#xff0c;我们的重点是简单&#xff0c;有效的解决方案&#xff0c;因此&#xff0c;最有价值的原则之一就是“保持简单和愚蠢”。 但是使用Hadoop map-reduce很难坚持这一点。 如果我们要评估多个Map Reduce作业中的数据&#xff0c;那么最终将得到与业务无关但…

行内元素和块元素以及行内块元素的特点

一、背景 初学html&#xff0c;接触很多标签 <h1>、<p>、<span>、<ul>、<em>等&#xff0c;当写出简单的小页面的时候&#xff0c;例如仅仅是一篇带有标题的文章&#xff0c;标题 <h1>标签单独一行&#xff0c;不管后面有多大的空间&…

软件测试的功能测试和性能测试,大型软件的功能测试流程及性能测试流程

大型软件具有涉及子模块繁多、建设过程复杂、功能全面、性能具有较高要求的特点。依据ISO/IEC 9126软件产品评估标准&#xff0c;需要对软件的功能性、可靠性、可用性、效率、可维护性、可移植性等方面进行评估。因此&#xff0c;需要有一种方法能够对大型软件进行测试&#xf…

vue 分模块打包 脚手架_Vue面试官最爱的底层源码问题,你可以这样回答!

最近看到身边很多人都在投简历&#xff0c;有因为企业裁员的&#xff0c;有因为自己想跳槽的&#xff0c;原因不一&#xff0c;但是最终大家都会需要接触到面试这个事情。但是很多人对待面试不够认真&#xff0c;只会等待结果&#xff0c;不去努力。所以这边想整理一些懒人面试…

re.containerbase.startinternal 子容器启动失败_Python项目容器化实践(二) Docker Machine和Docker Swarm...

前言这篇文章介绍Docker生态中的常被提到的Engine、Machine和Swarm&#xff0c;大家以了解为主&#xff0c;工作需要再深入。EngineDocker Engine其实就是我们常说的「Docker」&#xff0c;它是一个C/S模型(Client/Server)的应用&#xff0c;包含如下组件:Daemon。守护进程&…

基于设备树的TQ2440的中断(2)

下面以按键中断为例看看基于设备数的中断的用法&#xff1a; 设备树&#xff1a; tq2440_key {compatible "tq2440,key";interrupt-parent <&gpf>;interrupts <0 IRQ_TYPE_EDGE_FALLING>, <1 IRQ_TYPE_EDGE_FALLING>;key_3 <&gpf 2…

计算机里有个不能进入的磁盘分区,新电脑只有一个分区怎么办? 教你们如何不进pe给硬盘创建新分区!...

很多朋友新电脑刚买回来打开发现明明自己机械硬盘1T或者1T机械加128G固态&#xff0c;但是却只有一个或者两个分区&#xff0c;但是又不会分区现在教大家如何不用老毛桃大白菜之类的进pe系统里面就能直接创建新分区1 WinR输入diskmgmt.msc2进入磁盘管理可以查看本机的C盘与E盘的…

OSGi中的权限

在上一篇文章中 &#xff0c;我们介绍了为Java应用程序实现沙箱的方法&#xff0c;在其中我们可以安全地运行移动代码 。 这篇文章探讨了如何在OSGi环境中执行相同的操作。 OSGi OSGi规范 为Java定义了一个动态模块系统 。 因此&#xff0c;它是实施那种可以使您的应用程序动…

HTTP简单教程

目录 HTTP简介 HTTP工作原理 HTTP消息结构 客户端请求消息服务器响应消息实例 HTTP请求方法HTTP响应头信息HTTP状态码 HTTP状态码分类HTTP状态码列表 HTTP content-type对照表 HTTP简介 HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写&…

Reversed-Z详解

在3D渲染管线中&#xff0c;Z这个家伙几乎无处不在&#xff0c;如Z-Buffer&#xff0c;Early-Z&#xff0c;Z-Cull&#xff0c;Z-Test&#xff0c;Z-Write等等&#xff0c;稍有接触图形学的人都会对这些术语有所耳闻。 那么Z到底是什么呢&#xff1f;首先Z当然可以是任意坐标系…

pyqt开发的程序模板_小程序定制开发和模板开发要多少钱?有什么区别?

到现在&#xff0c;小程序开发已经有了1年多的历史&#xff0c;已经达到百万数量级。无论是小程序商城还是小程序游戏&#xff0c;其开发方式不外乎两种&#xff0c;一种是定制开发&#xff0c;另一种是模板开发。对于很多初次接触小程序的客户来说&#xff0c;还不知道小程序的…

实现字符串的编码转换,用以解决字符串乱码问题

引起乱码的情况很多~实质上 主要是字符串本身的编码格式 与程序所需要的编码格式不一致导致的。要解决乱码其实很简单&#xff0c; 分2步 &#xff1a; 1&#xff1a;获取到字符串 本身的编码 2&#xff1a;改变字符串编码 &#xff08;本身编码 -> 新编码&#xff09; 话不…

python运行原理_Python线程池及其原理和使用(超级详细)

系统启动一个新线程的成本是比较高的&#xff0c;因为它涉及与操作系统的交互。在这种情形下&#xff0c;使用线程池可以很好地提升性能&#xff0c;尤其是当程序中需要创建大量生存期很短暂的线程时&#xff0c;更应该考虑使用线程池。 线程池在系统启动时即创建大量空闲的线程…

Google Guava缓存

这篇文章是我在Google Guava上系列文章的续篇&#xff0c;这次涵盖了Guava Cache。 与HashMap或ConcurrentHashMap相比&#xff0c;Guava Cache提供了更大的灵活性和功能&#xff0c;但不像使用EHCache或Memcached那样繁重&#xff08;就此而言&#xff0c;它很健壮&#xff0c…

html 三列布局(两列自适应,一列固定宽度)

不做过多解释&#xff1a;主要是记录一个完整的布局样式&#xff0c;实现页面大致三列其中左右两列是自适应宽度&#xff0c;中间固定宽度效果。 不多少代码奉上&#xff1a; CSS样式代码&#xff1a; /*********************公共标签样式********************//************…

jsp常用动作

jsp:include 动态包含&#xff1b; jsp:forward 转发&#xff1b; jsp:useBean 实例化bean对象&#xff1b; jsp:setProperty 设置一个属性值 jsp:getProperty 获取一个属性值 jsp:param 动态传参数&#xff1b; jsp:plugin 生成一个插件 jsp:useBean 实例化一个对象…