嘉定网站建设哪里好,网站建设规划论文,wordpress店铺主题,湖南seo推广系统上次我们熟悉了ListenableFuture 。 我答应介绍更高级的技术#xff0c;即转换和链接。 让我们从简单的事情开始。 假设我们有从某些异步服务获得的ListenableFutureString 。 我们还有一个简单的方法#xff1a; Document parse(String xml) {//...我们不需要Strin… 上次我们熟悉了ListenableFuture 。 我答应介绍更高级的技术即转换和链接。 让我们从简单的事情开始。 假设我们有从某些异步服务获得的ListenableFutureString 。 我们还有一个简单的方法 Document parse(String xml) {//... 我们不需要String 我们需要Document 。 一种方法是简单地解析Future 等待它并在String上进行处理。 但是更优雅的解决方案是在结果可用后立即应用转换并将我们的方法视为始终返回ListenableFutureDocument 。 这很简单 final ListenableFutureString future //...final ListenableFutureDocument documentFuture Futures.transform(future, new FunctionString, Document() {Overridepublic Document apply(String contents) {return parse(contents);}
}); 或更可读 final FunctionString, Document parseFun new FunctionString, Document() {Overridepublic Document apply(String contents) {return parse(contents);}
};final ListenableFutureString future //...final ListenableFutureDocument documentFuture Futures.transform(future, parseFun); Java语法有一定的局限性但请专注于我们刚刚做的事情。 Futures.transform()不会等待基础的ListenableFutureString应用parse()转换。 相反它在后台注册了一个回调希望在给定将来完成时得到通知。 在适当的时候对我们动态透明地应用了此转换。 我们仍然有Future 但是这次包装了Document 。 因此让我们更进一步。 我们还有一个异步的可能长时间运行的方法用于计算给定Document 相关性 无论在这种情况下是什么 ListenableFuturecalculateRelevance(Document pageContents) {//... 我们可以以某种方式将其与我们已经拥有的ListenableFutureDocument吗 第一次尝试 final FunctionDocument, ListenableFutureDouble relevanceFun new FunctionDocument, ListenableFutureDouble() {Overridepublic ListenableFutureDouble apply(Document input) {return calculateRelevance(input);}
};final ListenableFutureString future //...
final ListenableFutureDocument documentFuture Futures.transform(future, parseFun);
final ListenableFutureListenableFutureDouble relevanceFuture Futures.transform(documentFuture, relevanceFun); 哎哟! Double Future的未来看起来不太好。 一旦我们解决了外部的未来我们也需要等待内部的未来。 绝对不优雅。 我们可以做得更好吗 final AsyncFunctionDocument, Double relevanceAsyncFun new AsyncFunctionDocument, Double() {Overridepublic ListenableFutureDouble apply(Document pageContents) throws Exception {return calculateRelevance(pageContents);}
};final ListenableFutureString future //comes from ListeningExecutorService
final ListenableFutureDocument documentFuture Futures.transform(future, parseFun);
final ListenableFutureDouble relevanceFuture Futures.transform(documentFuture, relevanceAsyncFun); 请非常仔细地查看所有类型和结果。 注意Function和AsyncFunction之间的区别。 最初我们有一个异步方法返回String future。 后来我们对其进行了转换以将String无缝转换为XML Document 。 内部将来完成后此转换将异步发生。 具有Document future我们想调用一个需要Document并返回Double future的方法。 如果调用relevanceFuture.get() 则我们的Future对象将首先等待内部任务完成其结果 String - Document 将等待外部任务并返回Double 。 我们还可以在relevanceFuture上注册回调该回调将在外部任务 calculateRelevance() 完成时触发。 如果您仍然在这里那就是更加疯狂的转变。 请记住所有这些都是循环发生的。 对于每个网站我们都有ListenableFutureString 我们将其异步转换为ListenableFutureDouble 。 所以最后我们使用ListListenableFutureDouble 。 这也意味着为了提取所有结果我们要么为每个ListenableFuture注册侦听器要么等待它们中的每个。 根本没有进步。 但是如果我们可以轻松地从ListListenableFutureDouble为ListenableFutureListDouble怎么办 仔细阅读-从期货清单到清单的未来。 换句话说不是拥有一堆小小的期货而是有一个将在所有子期货都完成后完成的期货–并且将结果一对一映射到目标列表。 猜猜Guava可以做到这一点 final ListListenableFutureDouble relevanceFutures //...;
final ListenableFutureListDouble futureOfRelevance Futures.allAsList(relevanceFutures); 当然这里也没有等待。 包装器ListenableFutureListDouble将在其子期货之一完成时得到通知。 最后一个孩子ListenableFutureDouble完成时外部将来也完成。 一切都是事件驱动的对您完全隐藏。 你认为就是这样吗 假设我们要计算整个集合中最大的相关性。 您可能现在已经知道我们不会等待ListDouble 。 相反我们将注册从ListDouble到Double final ListenableFutureDouble maxRelevanceFuture Futures.transform(futureOfRelevance, new FunctionListDouble, Double() {Overridepublic Double apply(ListDouble relevanceList) {return Collections.max(relevanceList);}
}); 最后我们可以侦听maxRelevanceFuture完成事件并使用JMS发送结果异步。 如果您迷路了这是完整的代码 private Document parse(String xml) {return //...
}private final FunctionString, Document parseFun new FunctionString, Document() {Overridepublic Document apply(String contents) {return parse(contents);}
};private ListenableFutureDouble calculateRelevance(Document pageContents) {return //...
}final AsyncFunctionDocument, Double relevanceAsyncFun new AsyncFunctionDocument, Double() {Overridepublic ListenableFutureDouble apply(Document pageContents) throws Exception {return calculateRelevance(pageContents);}
};//...final ListeningExecutorService pool MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)
);final ListListenableFutureDouble relevanceFutures new ArrayList(topSites.size());
for (final URL siteUrl : topSites) {final ListenableFutureString future pool.submit(new CallableString() {Overridepublic String call() throws Exception {return IOUtils.toString(siteUrl, StandardCharsets.UTF_8);}});final ListenableFutureDocument documentFuture Futures.transform(future, parseFun);final ListenableFutureDouble relevanceFuture Futures.transform(documentFuture, relevanceAsyncFun);relevanceFutures.add(relevanceFuture);
}final ListenableFutureListDouble futureOfRelevance Futures.allAsList(relevanceFutures);
final ListenableFutureDouble maxRelevanceFuture Futures.transform(futureOfRelevance, new FunctionListDouble, Double() {Overridepublic Double apply(ListDouble relevanceList) {return Collections.max(relevanceList);}
});Futures.addCallback(maxRelevanceFuture, new FutureCallbackDouble() {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