Guava文档翻译之ListenableFuture

ListenableFutureExplained

并发是一个困难的问题,但是使用强大而简单的抽象可以极大地简化并发问题。为了简化事情,Guava使用ListenableFuture继承了JDK的Future接口.

我们强烈建议你在所在代码里总是使用ListenableFuture,而不是Future,因为:

  • 大多数Future相关的接口需要它
  • 这比以后换成ListenableFuture更容易
  • 工具的提供者不需要为它们的方法分别提供Future和ListenableFuture的变体

接口 Interface

一个传统的Future代表一个异步计算的结果:一个可能已经得到结果或者还没结束的计算。一个Future可以作为一个正在进行中的计算的句柄(handle), 作为一个服务对我们的保证(promise),保证它会提供给我们一个结果。

一个ListenableFuture允许我们注册一个在计算完成时会执行的回调(callback),如果计算已经完成,就会立即执行回调。这个增加的简单功能可以让ListenableFuture支持很多基本的Future接口所不支持的操作。

ListenableFuture所增加的基本操作是addListener(Runnable, Executor), 它指明当这个Future代表的计算完成时,特定的Runnable将会在特定的Executor中执行。

填加回调 Adding Callbacks

大多数用户倾向于使用Futures.addCallback(ListenableFuture<V>, FutureCallback<V>, Executor),或者另一个默认使用MoreExecutors.sameThreadExecutor的版本,来在回调执行快速并且轻量的时候使用。一个需要实现两个方法 FutureCallback<V>

  • onSuccess(V),在future成功时执行的动作,基于future的结果。
  • onFailure(Throwable)当future失败时执行的动作,基于失败的原因。

创建 Creation

与JDK使用ExecutorService.submit(Callable)的方式来初始化一个异步的计算相类似,Guava提供了接口ListeningExecutorService,它会返回一个ListenableFuture而不像ExecutorService那样返回一个Future。如果想要把一个ExecutorService转化为一个ListeningExecutorService,只需要使用MoreExecutors.listeningDecorator(ExecutorService)。

ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = service.submit(new Callable<Explosion>() {
  public Explosion call() {
    return pushBigRedButton();
  }
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
  // we want this handler to run immediately after we push the big red button!
  public void onSuccess(Explosion explosion) {
    walkAwayFrom(explosion);
  }
  public void onFailure(Throwable thrown) {
    battleArchNemesis(); // escaped the explosion!
  }
});

或者,如果你之前用的是基于FutureTask的API,Guava提供了ListenableFutureTask.create(Callable<V>) 以及ListenableFutureTask.create(Runnable, V)。不像JDK,ListenableFutureTask并不是用来直接继承的。

如果你想要这样的抽象:你想直接设置future的值,而不是实现一个方法来计算这个值,考虑下继承 AbstractFuture<V> ,或者直接使用SettableFuture

如果你必须把其它API提供的Future转成ListenableFuture,你可能别无选择,而必须使用重量级 JdkFutureAdapters.listenInPoolThread(Future)的来把一个Future转成ListenableFuture. 只要情况允许,更好的选择就是修改原来的代码,让它返回一个ListenableFuture。

应用 Application

(译注:这个application应该理解成apply的名词,是‘apply a function to a value‘里的apply的意思, 请从函数式编程的角度理解)

使用ListenableFuture的最主要的原因是,它可以组成异步操作的复杂的处理链。

ListenableFuture<RowKey> rowKeyFuture = indexService.lookUp(query);
AsyncFunction<RowKey, QueryResult> queryFunction =
  new AsyncFunction<RowKey, QueryResult>() {
    public ListenableFuture<QueryResult> apply(RowKey rowKey) {
      return dataService.read(rowKey);
    }
  };
ListenableFuture<QueryResult> queryFuture = Futures.transform(rowKeyFuture, queryFunction, queryExecutor);

(译注:如果懂Scala的话,这段代码大体相当于rowKeyFuture.map(dataService.read)(queryExecutor), 要短了非常多,也更好理解。但是Scala的Future好像不像ListenableFuture可以注册多个监听器)

有很多其它的操作也可以被ListenableFuture高效的支持,但是Future就不行。不同的操作可以在不同的executor中执行,一个ListenableFuture也可以有多个等待执行的动作。

当很多个操作都要在另一个操作开始后立即执行--也就是扇出(fan-out)--ListenableFuture可以做到这点:它可以触发所有那些的需要执行的回调。多做一点工作,我们就可以扇入(fan-in),或者触发一个ListenableFuture,在其它所有的Future都完成以后,它会立即执行: 一个例子是the implementation of Futures.allAsList

Method Description See also
transform(ListenableFuture<A>, AsyncFunction<A, B>, Executor)* Returns a newListenableFuturewhose result is the product of applying the givenAsyncFunction to the result of the givenListenableFuture. transform(ListenableFuture<A>, AsyncFunction<A, B>)
transform(ListenableFuture<A>, Function<A, B>, Executor) Returns a newListenableFuturewhose result is the product of applying the given Functionto the result of the givenListenableFuture. transform(ListenableFuture<A>, Function<A, B>)
allAsList(Iterable<ListenableFuture<V>>) Returns aListenableFuturewhose value is a list containing the values of each of the input futures, in order. If any of the input futures fails or is cancelled, this future fails or is cancelled. allAsList(ListenableFuture<V>...)
successfulAsList(Iterable<ListenableFuture<V>>) Returns aListenableFuturewhose value is a list containing the values of each of the successful input futures, in order. The values corresponding to failed or cancelled futures are replaced with null. successfulAsList(ListenableFuture<V>...)
Method 方法 Description 描述 See also 参见
transform(ListenableFuture<A>, AsyncFunction<A, B>, Executor)*
Returns a newListenableFuture whose result is the product of applying the given AsyncFunction to the result of the given ListenableFuture.

返回一个新的ListenableFuture, 它的结果是把给定的ListenableFuture的结果应用于给定的异步函数的结果(译注:意思是把给定的ListenableResult的result作为参数调用给定的异步函数)

transform(ListenableFuture<A>, AsyncFunction<A, B>)
transform(ListenableFuture<A>, Function<A, B>, Executor)
Returns a new ListenableFuture whose result is the product of applying the given Functionto the result of the given ListenableFuture.

返回一个新的ListenableFuture,它的结果是把给定的ListenableFuture的结果应用于给定的函数的结果

transform(ListenableFuture<A>, Function<A, B>)
allAsList(Iterable<ListenableFuture<V>>)
Returns a ListenableFuture whose value is a list containing the values of each of the input futures, in order. If any of the input futures fails or is cancelled, this future fails or is cancelled.

返回一个新的ListenableFuture,它的结果一个list, 这个list包括了给定的一系列ListenableFuture的结果,list的元素按照这些给定的ListenableFuture的顺序。如果给定的这些futures中有任何一个被取消了或者失败了,被返回的这个ListenableFuture就会被取消或失败。

allAsList(ListenableFuture<V>...)
successfulAsList(Iterable<ListenableFuture<V>>)
Returns aListenableFuturewhose value is a list containing the values of each of the successful input futures, in order. The values corresponding to failed or cancelled futures are replaced with null.

返回一个新的ListenableFuture,它的值是一个list,这个list包括了每一个成功执行的future,按照给出的顺序。跟失败或者被取消的future相关的值会被设成null

successfulAsList(ListenableFuture<V>...)

* An AsyncFunction<A, B> provides one method, ListenableFuture<B> apply(A input). It can be used to asynchronously transform a value.

一个提供了一个方法AsyncFunction<A, B>,ListenableFuture<B> apply(A input)。它可以被用于异步地转换一个值。

List<ListenableFuture<QueryResult>> queries;
// The queries go to all different data centers, but we want to wait until they‘re all done or failed.

ListenableFuture<List<QueryResult>> successfulQueries = Futures.successfulAsList(queries);

Futures.addCallback(successfulQueries, callbackOnSuccessfulQueries);

CheckedFuture

Guava也提供了一个CheckedFuture<V, X extends Exception>接口。一个CheckedFuture 也是一个ListenableFuture,包括了各种版本的可以抛出受检异常的方法。这使得创建一个执行逻辑可能抛出异常的Future更加容易。如果想要把一个ListenableFuture转成一个CheckedFuture, 可以使用Futures.makeChecked(ListenableFuture<V>, Function<Exception, X>).



总结:

ListenableFuture提供了很有价值的对JDK并发库的补充。不过同样的功能,Scala提供的Future的功能要更强大,而且Scala的语法也使得代码更简单易懂。实际上,Promise也是很强大的一种抽象,这篇Guava的文章只简单提了一下SettableFuture。想要更深入了解的可以看一下Scala的文档,这个有人翻译了,页面的右上角可以选择中文版。

Futures and Promises

时间: 2024-08-09 07:17:14

Guava文档翻译之ListenableFuture的相关文章

google Guava包的ListenableFuture解析

原文地址  译者:罗立树  校对:方腾飞 并发编程是一个难题,但是一个强大而简单的抽象可以显著的简化并发的编写.出于这样的考虑,Guava 定义了 ListenableFuture接口并继承了JDK concurrent包下的Future 接口. 我们强烈地建议你在代码中多使用ListenableFuture来代替JDK的 Future, 因为: 大多数Futures 方法中需要它. 转到ListenableFuture 编程比较容易. Guava提供的通用公共类封装了公共的操作方方法,不需要提

Guava文档翻译之 Guava简介

用户指南 User Guide Guava项目包括了一些Google的核心库,是我们在基于Java的项目中所依赖的,这些库包括:集合,缓存,对基本类型的支持,并发库,通用的注解,字符串处理,I/O,等等.这些工具的每一个真的都在被Google每天使用着,而且是在生产系统中. 但是只是在Javadoc中寻觅不是学会怎么使用一个库的最有效的方法.在此,我们试图对Guava的一些最流行和强大的特性做出良好的阐述. 这个wiki还没有完工,它的有些部分仍然在构建中. 基础工具:让使用Java这个语言更令

Guava并发:ListenableFuture与RateLimiter示例

ListenableFuture顾名思义就是可以监听的Future,它是对java原生Future的扩展增强 RateLimiter类似于JDK的信号量Semphore,他用来限制对资源并发访问的线程数,本文介绍RateLimiter使用 Guava并发 ListenableFuture RateLimiter 目录[-] 概念 代码示例 Guava版本 源码:http://www.jinhusns.com/Products/Download/?type=xcj 概念 ListenableFut

Guava文档翻译之 Service

概览 Guava的接口代表了一个有运行状态的对象,有启动和停止的方法.比如网络服务器,RPC服务器,以及计时器等,都可以实现Service接口.掌管像这样的服务的状态,需要正确地管理启动和关闭,因此会是繁琐的,特别是牵扯到多线程和调度.Guava提供了一个基本的骨架,可以帮你管理状态逻辑,以及同步的细节 一个Service的通常的生命周期是 Service.State.NEW 到 Service.State.STARTING 到 Service.State.RUNNING 到 Service.S

ListenableFuture in Guava

ListenableFuture的说明 并发编程是一个难题,但是一个强大而简单的抽象可以显著的简化并发的编写.出于这样的考虑,Guava 定义了 ListenableFuture接口并继承了JDK concurrent包下的Future 接口,ListenableFuture 允许你注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用,  或者在运算(多线程执行)完成后立即执行.这样简单的改进,使得可以明显的支持更多的操作,这样的功能在JDK concurrent中的Fut

Guava Futures异步回调机制源码解析

本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/51758194 1.前言 在前两篇文章中简单阐述了Java Future 和Guava ListenableFuture及其相关的应用.我们发现Guava ListenableFuture提供了比Java Future更加强大的功能,而在Google Guava并发包中,某些情况下,Futures这个类起到了不可或缺的作用,而ListenableFuture

GUAVA-ListenableFuture实现回调

随着软件开发的不断进步,在实际的开发应用中,可能一次请求需要查询若干次数据库或者调用若干次第三方,按照传统的串行执行的话,会大大增加响应时间,无法满足业务需求,更无法满足用户迫切需要响应迅速的愿望.对此,我们需要针对网络请求或内部调用中包含的"多任务"进行异步处理,并行去执行这些"任务",这样就就会大大减小响应时间.本文是基于guava中的ListenableFuture来实现的. 测试代码: 1 package com.study1; 2 3 import jav

监听器模式、观察者模式

最近在学习netty的时候,发现里面用到了监听器模式,感觉非常实用,以前看设计模式的时候只是看,并没有用上.其实这是一个非常重要并实用的设计模式,在很多框架里面都用到了. netty里面的应用: serverBootstrap.bind(8000).addListener(new GenericFutureListener<Future<? super Void>>() { public void operationComplete(Future<? super Void&g

你应该这样去开发接口:Java多线程并行计算

所谓的高并发除了在架构上的高屋建瓴,还得需要开发人员在具体业务开发中注重自己的每一行代码.每一个细节,面子有的同时,更重要的还是要有里子. 面对性能,我们一定要有自己的工匠精神,不可以对任何一行代码妥协! 今天和大家分享在业务开发中如何降低接口响应时间的一个小技巧,也是大家日常开发中比较普遍存在的一个问题,即如何提高程序的并行计算能力? 本文主要包含以下内容: 顺序执行很慢 线程池+Future并行计算 使用Java8的CompletableFuture 使用Guava的ListenableFu