先进的ListenableFuture功能

上次我们熟悉了ListenableFuture 。 我答应介绍更高级的技术,即转换和链接。 让我们从简单的事情开始。 假设我们有从某些异步服务获得的ListenableFuture<String> 。 我们还有一个简单的方法:

Document parse(String xml) {//...

我们不需要String ,我们需要Document 。 一种方法是简单地解析Future等待它)并在String上进行处理。 但是,更优雅的解决方案是在结果可用后立即应用转换,并将我们的方法视为始终返回ListenableFuture<Document> 。 这很简单:

final ListenableFuture<String> future = //...final ListenableFuture<Document> documentFuture = Futures.transform(future, new Function<String, Document>() {@Overridepublic Document apply(String contents) {return parse(contents);}
});

或更可读:

final Function<String, Document> parseFun = new Function<String, Document>() {@Overridepublic Document apply(String contents) {return parse(contents);}
};final ListenableFuture<String> future = //...final ListenableFuture<Document> documentFuture = Futures.transform(future, parseFun);

Java语法有一定的局限性,但请专注于我们刚刚做的事情。 Futures.transform()不会等待基础的ListenableFuture<String>应用parse()转换。 相反,它在后台注册了一个回调,希望在给定将来完成时得到通知。 在适当的时候对我们动态透明地应用了此转换。 我们仍然有Future ,但是这次包装了Document

因此,让我们更进一步。 我们还有一个异步的,可能长时间运行的方法,用于计算给定Document 相关性 (无论在这种情况下是什么):

ListenableFuturecalculateRelevance(Document pageContents) {//...

我们可以以某种方式将其与我们已经拥有的ListenableFuture<Document>吗? 第一次尝试:

final Function<Document, ListenableFuture<Double>> relevanceFun = new Function<Document, ListenableFuture<Double>>() {@Overridepublic ListenableFuture<Double> apply(Document input) {return calculateRelevance(input);}
};final ListenableFuture<String> future = //...
final ListenableFuture<Document> documentFuture = Futures.transform(future, parseFun);
final ListenableFuture<ListenableFuture<Double>> relevanceFuture = Futures.transform(documentFuture, relevanceFun);

哎哟! Double Future的未来,看起来不太好。 一旦我们解决了外部的未来,我们也需要等待内部的未来。 绝对不优雅。 我们可以做得更好吗?

final AsyncFunction<Document, Double> relevanceAsyncFun = new AsyncFunction<Document, Double>() {@Overridepublic ListenableFuture<Double> apply(Document pageContents) throws Exception {return calculateRelevance(pageContents);}
};final ListenableFuture<String> future = //comes from ListeningExecutorService
final ListenableFuture<Document> documentFuture = Futures.transform(future, parseFun);
final ListenableFuture<Double> relevanceFuture = Futures.transform(documentFuture, relevanceAsyncFun);

请非常仔细地查看所有类型和结果。 注意FunctionAsyncFunction之间的区别。 最初,我们有一个异步方法返回String future。 后来,我们对其进行了转换,以将String无缝转换为XML Document 。 内部将来完成后,此转换将异步发生。 具有Document future,我们想调用一个需要Document并返回Double future的方法。

如果调用relevanceFuture.get() ,则我们的Future对象将首先等待内部任务完成,其结果( String -> Document )将等待外部任务并返回Double 。 我们还可以在relevanceFuture上注册回调,该回调将在外部任务( calculateRelevance() )完成时触发。 如果您仍然在这里,那就是更加疯狂的转变。

请记住,所有这些都是循环发生的。 对于每个网站,我们都有ListenableFuture<String> ,我们将其异步转换为ListenableFuture<Double> 。 所以最后我们使用List<ListenableFuture<Double>> 。 这也意味着,为了提取所有结果,我们要么为每个ListenableFuture注册侦听器,要么等待它们中的每个。 根本没有进步。 但是,如果我们可以轻松地从List<ListenableFuture<Double>>ListenableFuture<List<Double>>怎么办? 仔细阅读-从期货清单到清单的未来。 换句话说,不是拥有一堆小小的期货,而是有一个将在所有子期货都完成后完成的期货–并且将结果一对一映射到目标列表。 猜猜,Guava可以做到这一点!

final List<ListenableFuture<Double>> relevanceFutures = //...;
final ListenableFuture<List<Double>> futureOfRelevance = Futures.allAsList(relevanceFutures);

当然,这里也没有等待。 包装器ListenableFuture<List<Double>>将在其期货之一完成时得到通知。 最后一个孩子ListenableFuture<Double>完成时,外部将来也完成。 一切都是事件驱动的,对您完全隐藏。

你认为就是这样吗? 假设我们要计算整个集合中最大的相关性。 您可能现在已经知道,我们不会等待List<Double> 。 相反,我们将注册从List<Double>Double

final ListenableFuture<Double> maxRelevanceFuture = Futures.transform(futureOfRelevance, new Function<List<Double>, Double>() {@Overridepublic Double apply(List<Double> relevanceList) {return Collections.max(relevanceList);}
});

最后,我们可以侦听maxRelevanceFuture完成事件,并使用JMS发送结果(异步!)。 如果您迷路了,这是完整的代码:

private Document parse(String xml) {return //...
}private final Function<String, Document> parseFun = new Function<String, Document>() {@Overridepublic Document apply(String contents) {return parse(contents);}
};private ListenableFuture<Double> calculateRelevance(Document pageContents) {return //...
}final AsyncFunction<Document, Double> relevanceAsyncFun = new AsyncFunction<Document, Double>() {@Overridepublic ListenableFuture<Double> apply(Document pageContents) throws Exception {return calculateRelevance(pageContents);}
};//...final ListeningExecutorService pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)
);final List<ListenableFuture<Double>> relevanceFutures = new ArrayList<>(topSites.size());
for (final URL siteUrl : topSites) {final ListenableFuture<String> future = pool.submit(new Callable<String>() {@Overridepublic String call() throws Exception {return IOUtils.toString(siteUrl, StandardCharsets.UTF_8);}});final ListenableFuture<Document> documentFuture = Futures.transform(future, parseFun);final ListenableFuture<Double> relevanceFuture = Futures.transform(documentFuture, relevanceAsyncFun);relevanceFutures.add(relevanceFuture);
}final ListenableFuture<List<Double>> futureOfRelevance = Futures.allAsList(relevanceFutures);
final ListenableFuture<Double> maxRelevanceFuture = Futures.transform(futureOfRelevance, new Function<List<Double>, Double>() {@Overridepublic Double apply(List<Double> relevanceList) {return Collections.max(relevanceList);}
});Futures.addCallback(maxRelevanceFuture, new FutureCallback<Double>() {@Overridepublic void onSuccess(Double result) {log.debug("Result: {}", result);}@Overridepublic void onFailure(Throwable t) {log.error("Error :-(", t);}
});

它值得吗? 是的没有是的 ,因为我们了解了一些与期货/承诺一起使用的非常重要的构造和原语:链接,映射(转换)和归约。 该解决方案在CPU利用率方面非常出色-无需等待,阻塞等。请记住, Node.js的最大优势在于其“无阻塞”策略。 在Netty期货中也无处不在。 最后但并非最不重要的一点是,它感觉非常实用

另一方面,主要是由于Java语法冗长和缺乏类型推断(是的,我们将很快进入Scala),代码似乎非常难以阅读,难以遵循和维护。 好吧,在某种程度上,这适用于所有消息驱动的系统。 但是,只要我们不发明更好的API和原语,我们就必须学习生存并利用异步,高度并行的计算。

如果您想进一步尝试ListenableFuture ,请不要忘记阅读官方文档 。

参考: NoBlogDefFound博客中来自我们的JCG合作伙伴 Tomasz Nurkiewicz的高级ListenableFuture功能 。

翻译自: https://www.javacodegeeks.com/2013/03/advanced-listenablefuture-capabilities.html

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

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

相关文章

修改内表数据并输出结果

*定义结构ty_salesTYPES:BEGIN OF ty_sales, customerid(3) TYPE n, productid(3) TYPE n, orderid(3) TYPE n, customername(10) TYPE c, amount TYPE i, END OF ty_sales.*定义内表和工作区DATA: it_sales TYPE STANDARD TABLE OF ty_sales WITH KEY customerid …

关于css透明度的问题

先看background和background-color background:可以设置背景颜色&#xff0c;背景图片&#xff0c;还有定位。默认background:no-repeat; background-color:只可以设置背景颜色。默认background:repeat; 设置透明度的方式有两种&#xff1a; 第一种&#xff1a; opacity:0.…

java多字段排序,java8 stream多字段排序的实现

很多情况下sql不好解决的多表查询,临时表分组,排序,尽量用java8新特性stream进行处理使用java8新特性,下面先来点基础的List list; 代表某集合//返回 对象集合以类属性一升序排序list.stream().sorted(Comparator.comparing(类::属性一));//返回 对象集合以类属性一降序排序 注…

C#调用Power Shell 管理Office365 执行脚本时遇到的问题

Power Shell管理Office参考http://www.mamicode.com/info-detail-494553.html C#调用Power Shell 参考 https://www.cnblogs.com/chenkai/archive/2010/11/09/1872471.html string pwd "**********";string userName "**********";StringBuilder ss new…

java.util.concurrent.Future基础

在此&#xff0c;我开始撰写一系列有关编程语言中的未来概念&#xff08;也称为promise或delays &#xff09;的文章&#xff0c;标题为&#xff1a; Back to the Future 。 由于对异步&#xff0c;事件驱动&#xff0c;并行和可伸缩系统的需求不断增长&#xff0c;所以期货是非…

javaweb(三十七)——获得MySQL数据库自动生成的主键

测试脚本如下&#xff1a; 1 create table test1 2 ( 3 id int primary key auto_increment, 4 name varchar(20) 5 ); 测试代码&#xff1a; 1 package me.gacl.demo;2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; …

如何隐藏 video 元素的下载按钮

1. 使用 video 元素的 ControlList API <video controls controlsList"nodownload"></video> 通过 ControList API&#xff0c;不仅可以通过设置 nodownload 来隐藏下载按钮&#xff0c;还可以设置 nofullscreen 隐藏全屏按钮, 以及noremoteplayback 等…

基于Matlab的模拟通信实验平台设计,【通信原理仿真实验】通信原理虚拟实验仿真平台的设计和实现_玛雅作文网...

作文「通信原理虚拟实验仿真平台的设计和实现」共有 4564 个字&#xff0c;其中有 2704 个汉字&#xff0c;1316 个英文&#xff0c;162 个数字&#xff0c;382 个标点符号。作者佚名&#xff0c;请您欣赏。玛雅作文网荟萃众多优秀学生作文&#xff0c;如果想要浏览更多相关作文…

2018/3/1 省选模拟考试 50分

T1 30分模拟暴力&#xff0c;40分树的直径。拿了0分。&#xff08;空间开小了爆了&#xff0c;因为缩点之后是又建了一次图&#xff0c;两个边的编号tot没分开&#xff0c;mdzz&#xff09; 只写了后40分&#xff0c;而这40分中有20分不需要边双连通分量。写了一个类似于强连通…

DNS缓存服务器的配置步骤

yum安装bind 编辑主配置文件/etc/named.conf 修改全局配置文件段 listen-on port 53 {172.16.19.45;}; //allow-query dnssec-enable no ; dnssec-validation no; dnssec-lookaside no; 检查配置文件是否修改正确 named-checkconf /etc/named.conf 重启na…

信号与系统 徐亚宁 matlab程序,信号与系统(第4版)

第1章绪论11信号与系统12信号的描述与分类13系统的描述与分类131连续时间LTI系统及其描述132离散时间LTI系统及其描述14系统的基本特性15信号与系统分析方法概述16MATLAB 基本知识161MATLAB简介162MATLAB快速入门本章学习指导习题上机练习第2章连续…

骆驼和春天的Drools决策表

正如我在之前的文章中所展示的那样&#xff0c; JBoss Drools是一个非常有用的规则引擎 。 唯一的问题是&#xff0c;对于非技术人员而言&#xff0c;以Rule语言创建规则可能会非常复杂。 这就是为什么可以提供一种轻松的方式来创建业务规则的方法-在电子表格中创建决策表&…

UA记录

安卓QQ内置浏览器UA: Mozilla/5.0 (Linux; Android 5.0; SM-N9100 Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36 V1_AND_SQ_5.3.1_196_YYB_D QQ/5.3.1.2335 NetType/WIFI 安卓微信内置浏览器UA: Mozilla/5.0 (Linu…

酷炫,用Html5/CSS实现文字阴影

前两天有一个学html5前端小美女问我一个有关文字阴影的效果怎么去实现。她和我说文字阴影嘛,她也知道text-shadow,.但是却做不出想要的样子,其实css3的新功能是很强大的,不要把你的思想太过于局限化,好了,闲话也不多说,咱们就先来看看这个文本阴影. 一.文字阴影text-shadow 文…

从xtrabackup备份恢复单表【转】

目前对MySQL比较流行的备份方式有两种&#xff0c;一种上是使用自带的mysqldump&#xff0c;另一种是xtrabackup&#xff0c;对于数据时大的环境&#xff0c;普遍使用了xtrabackupbinlog进行全量或者增量备份&#xff0c;那么如何快速的从xtrabackup备份中恢复单张表呢&#xf…

Java:放心(或非常容易)

最近&#xff0c;我不得不编写一些Java代码以通过HTTP 使用 REST服务 。 我决定使用RestEasy的客户端库&#xff0c;该框架是我大部分时间用来公开Java REST服务的框架&#xff0c;因为它也实现了官方的JAX-RS规范。 我对规范定义的注释驱动方法非常满意&#xff0c;这使REST服…

php输出json到表格,PHP中把数据库查询结果输出为json格式

header("Content-type:text/html;charsetutf-8");//字符编码设置$servername "localhost";$username "root";$password "root";$dbname "tjks";// 创建连接$con mysqli_connect($servername, $username, $password, $db…

CSS中的overflow属性

overflow属性 如果元素中的内容超出了给定的宽度和高度属性&#xff0c;overflow 属性可以确定是否显示滚动条&#xff0c;是否隐藏溢出部分等行为&#xff0c;规定当内容溢出元素框时发生的事情。 可能的值有&#xff1a; visible&#xff1a;默认值。内容不会被修剪&#xff…

COGS 13. 运输问题4

★★☆ 输入文件&#xff1a;maxflowd.in 输出文件&#xff1a;maxflowd.out 简单对比时间限制&#xff1a;1 s 内存限制&#xff1a;128 MB 【问题描述】一个工厂每天生产若干商品&#xff0c;需运输到销售部门进行销售。从产地到销地要经过某些城镇&#xff0c;有不同…

Java –手工Classloader隔离

在最近的项目中&#xff0c;我们遇到了一个典型的库冲突问题 。 我们可以控制的一个组件需要特定版本的Apache Commons库&#xff0c;而另一个组件则需要一个不同的版本。 由于外部限制&#xff0c; 我们无法在Container级别指定任何类加载隔离 。 这不是我们的选择。 相反&…