这篇文章是我在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

Google Guava –期货相关推荐

  1. 谷歌guava_Google Guava –期货

    谷歌guava 这篇文章是我在Google Guava上的系列文章的延续,这次涵盖了Future. Futures类是用于使用Future / ListenableFuture接口的静态实用程序方法的 ...

  2. Error:Could not download guava.jar (com.google.guava:guava:19.0): No cached version available for of

    今天从git导入demo 报错 Error:Could not download guava.jar (com.google.guava:guava:19.0): No cached version ...

  3. 为什么我不建议你用阿里巴巴Java规范,而使用 Google Guava 编程?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来自 | 张丰哲 链接 | www.jianshu.com ...

  4. 为什么推荐 Java 程序员使用 Google Guava 编程

    点击上方"方志朋",选择"设为星标" 做积极的人,而不是积极废人 来自 | 张丰哲 链接 | www.jianshu.com/p/97778b21bd00 前言 ...

  5. [Google Guava] 1.3-常见Object方法

    原文链接 译者: 沈义扬 equals 当一个对象中的字段可以为null时,实现Object.equals方法会很痛苦,因为不得不分别对它们进行null检查.使用Objects.equal帮助你执行n ...

  6. Google Guava Collections 使用介绍

    原帖http://www.open-open.com/lib/view/open1325143343733.html 简介: Google Guava Collections 是一个对 Java Co ...

  7. [Google Guava] 3-缓存

    原文地址  译文地址    译者:许巧辉  校对:沈义扬 范例 01 LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder() ...

  8. [Google Guava] 11-事件总线

    原文链接 译文连接 译者:沈义扬 传统上,Java的进程内事件分发都是通过发布者和订阅者之间的显式注册实现的.设计EventBus就是为了取代这种显示注册方式,使组件间有了更好的解耦.EventBus ...

  9. [Google Guava] 2.4-集合扩展工具类

    原文链接 译文链接 译者:沈义扬,校对:丁一 简介 有时候你需要实现自己的集合扩展.也许你想要在元素被添加到列表时增加特定的行为,或者你想实现一个Iterable,其底层实际上是遍历数据库查询的结果集 ...

最新文章

  1. 利用追赶法来求解方程Ax=b的C++程序
  2. 江苏省计算机学会科学技术奖,孙国梓
  3. 详细讲解Python中的self;什么是self?self的传参问题?
  4. java语言精粹_java 成神之路 (一)
  5. 源码nginx+php
  6. 可视化排班管理_人事工资管理系统就选i人事,提升算薪效率聚焦战略决策
  7. 群晖3617可以有几个网卡_一步到位,购入群晖920+和它的小伙伴们
  8. delphi csdn论坛技巧收藏贴
  9. 深圳市计算机软件著作权资助,深圳市计算机软件著作权登记资助管理实施细则...
  10. 英国essay与澳洲essay写作区别以及注意事项
  11. 跟读 播放器 android,安卓手机英语学习利器 android 英语复读 跟读 练听力 练口语...
  12. android友盟微信授权登录清除,【转载】Android友盟SDK微信授权登录接入
  13. 和中国移动对接短信平台
  14. Python基础提高
  15. 因为一个小功能,我对微信手机号转账的好感度加了10分
  16. python自动识别简单图片中的文字
  17. IDEA 更新到 2021.2.3 咋样?【2021.3、2021.3.1看评论区】
  18. TCP握手机制、TCP长连接和短连接、TCP 保活机制 、心跳机制
  19. Ubuntu 16.04 英伟达驱动、常用软件以及虚拟环境的安装
  20. Idea 中解决git冲突

热门文章

  1. python开发stm32软件_ADB+Python+STM32 实现 微信跳一跳辅助
  2. date转timestamp格式_技术分享 | MySQL:timestamp 时区转换导致 CPU %sys 高的问题
  3. 转:并发与并行的区别
  4. intro to JNDI
  5. SpringBoot整合Redis要注意的那些
  6. java gradle构建_在Gradle中为JPMS构建Java 6-8库
  7. 困难是成功路上的垫脚石_Java是开发的垫脚石。 学习吧!
  8. system.gc 性能_使用这些先进的GC技术提高应用程序性能
  9. maven 生成本地库_在2017年从Maven工件生成P2存储库
  10. guice 实例_使用Google Guice消除实例之间的歧义