前言:
本章介绍goole Guava 包的 ListenableFuture,也就是开源的Java Library Guaa中的一个并发编程的辅助类,它笨神是继承是java的Future。并发是一个很难的问题,但它是由具有强大和简单的抽象工作显著简化。为了简化事情,Guava扩展了来自JDK的Future从而得到 ListenableFuture。并发编程是一个难题,但是一个强大而简单的抽象可以显著的简化并发的编写。出于这样的考虑,Guava 定义le ListenableFuture
。
我们强烈地建议你在代码中多使用ListenableFuture来代替JDK的 Future, 因为:
- *大多数Futures 方法中需要它。
- *转到ListenableFuture 编程比较容易。
- *Guava提供的通用公共类封装了公共的操作方方法,不需要提供Future和ListenableFuture的扩展方法。
接口:
ListenableFuture 中的基础方法是addListener(Runnable, Executor)
该方法会在多线程运算完的时候,指定的Runnable参数传入的对象会被指定的Executor执行。
添加回调(Callbacks):
大多数用户喜欢使用Futures.addCallback(ListenableFuture<V>, FutureCallback<V>, Executor)
,或默认使用的版本MoreExecutors.sameThreadExecutor()
,以便在回调快速轻便时使用。A FutureCallback<V>
实现两种方法:
onSuccess(V)
在Future执行成功时去执行,取得成功的结果onFailure(Throwable)
,在Future执行失败时去执行失败, 取得失败的结果
创建:
ExecutorService.submit(Callable)
的方法来启动异步计算,Guava提供的ListeningExecutorService
接口,它
ListenableFuture
,而
ExecutorService
将返回普通的Future
。要转换ExecutorService
成一个
ListeningExecutorService
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
com.google.common.util.concurrent.ListenableFuture<Object> submit = service.submit(new Callable<Object>() {
public Object call(){
return "回调参数success";
}
});
Futures.addCallback(submit, new FutureCallback<Object>() {
@Override
public void onSuccess(Object result) {
System.out.println("result = " + result);
}
@Override
public void onFailure(Throwable t) {
System.out.println("t = " + t);
}
});
另外,如果你是从FutureTask转换而来的,Guava的API提供了
ListenableFutureTask.create(Callable<V>)
和API转换
ListenableFutureTask.create(Runnable, V)
。和 JDK不同的是, ListenableFutureTask 不能随意被继承(译者注:ListenableFutureTask中的done方法实现了调用listener的操作)。
如果你喜欢抽象的方式来设置Future的值,而不是想实现接口中的方法,可以考虑继承抽象类
假如你必须将其它API提供的Future转换成ListenableFuture,没有别的方法你只能采用硬编码的方式,使用JdkFutureAdapters.listenInPoolThread(Future)
将其转换Future
为ListenableFuture
。尽可能地采用修改原生的代码返回 ListenableFuture会更好一些。
应用(Application):
使用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.transformAsync(rowKeyFuture, queryFunction, queryExecutor);
ListenableFuture
,而不能单独支持
Future
。不同的操作可能由不同的执行者执行,单个操作
ListenableFuture
可以有多个动作等待。
当一个操作开始的时候其他的一些操作也会尽快开始执行–“fan-out”–ListenableFuture 能够满足这样的场景:促发所有的回调(callbacks)。反之更简单的工作是,同样可以满足“fan-in”场景,促发ListenableFuture 获取(get)计算结果,同时其它的Futures也会尽快执行:可以参考Futures.allAsList
fan-in和fan-out是软件设计的一个术语,可以参考这里:http://baike.baidu.com/view/388892.htm#1或者看这里的解析Design Principles: Fan-In vs Fan-Out,这里fan-out的实现就是封装的ListenableFuture通过回调,调用其它代码片段。fan-in的意义是可以调用其它Future
方法 | 描述 | 参考 |
---|---|---|
transformAsync(ListenableFuture<A>, AsyncFunction<A, B>, Executor) * | 返回一个新的ListenableFuture ,该ListenableFuture 返回的result是由传入的AsyncFunction 参数指派到传入的 ListenableFuture中. | transformAsync(ListenableFuture<A>, AsyncFunction<A, B>) |
transform(ListenableFuture<A>, Function<A, B>, Executor) | 返回一个新的ListenableFuture ,该ListenableFuture 返回的result是由传入的Function 参数指派到传入的 ListenableFuture中. | transform(ListenableFuture<A>, Function<A, B>) |
allAsList(Iterable<ListenableFuture<V>>) | 返回一个ListenableFuture ,该ListenableFuture 返回的result是一个List,List中的值是每个ListenableFuture的返回值,假如传入的其中之一fails或者cancel,这个Future fails 或者canceled | allAsList(ListenableFuture<V>...) |
successfulAsList(Iterable<ListenableFuture<V>>) | 返回一个ListenableFuture ,该Future的结果包含所有成功的Future,按照原来的顺序,当其中之一Failed或者cancel,则用null替代 | successfulAsList(ListenableFuture<V>...) |
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,
包含可以抛出被检查异常的多个get方法的版本。这使得创建一个执行可以更容易地执行可以抛出异常的逻辑。要转换ListenableFuture
成a CheckedFuture
,使用Futures.makeChecked(ListenableFuture<V>, Function<Exception, X>)
。这样使得创建一个在执行逻辑中可以抛出异常的Future更加容易 。将 ListenableFuture 转换成CheckedFuture。使用Futures.makeChecked(ListenableFuture<V>, Function<Exception, X>)
。
接下来,看一个例子,合并多个人物的结果集
public void test() throws Exception {
ListeningExecutorService service1 = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Object> submit1 = service1.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
Thread.sleep(1000);
System.out.println("call future1");
return "1";
}
});
com.google.common.util.concurrent.ListenableFuture<Object> submit2 = service1.submit(new Callable<Object>() {
@Override
public Object call() throws Exception {
Thread.sleep(1000);
System.out.println("call future2");
return "2";
}
});
ListenableFuture<List<Object>> listListenableFuture = Futures.allAsList(submit1, submit2);
ListenableFuture<String> transform = Futures.transform(listListenableFuture, new AsyncFunction<List<Object>, String>() {
@Override
public com.google.common.util.concurrent.ListenableFuture<String> apply(List<Object> input) throws Exception {
return Futures.immediateFuture(String.format("success future %s",input));
}
});
Futures.addCallback(transform, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println(result.getClass());
System.out.println("success:"+result);
}
@Override
public void onFailure(Throwable t) {
System.out.println("error:" + t.getMessage());
}
});
//获取值
System.out.println("transform:"+transform.get(3000, TimeUnit.MINUTES));
}
下面的例子是单个任务:
public void test3() throws Exception {
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
// 执行任务
final ListenableFuture<String> listenableFuture = executorService.submit(new Callable<String>() {
public String call() throws Exception {
System.out.println("new task 。。。");
TimeUnit.SECONDS.sleep(1);
return "test";
}
});
// 绑定任务以及回调函数
Futures.addCallback(listenableFuture, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
String str = "";
try {
str = listenableFuture.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("integer:" + str);
System.out.println("result:" + result);
}
@Override
public void onFailure(Throwable t) {
System.out.println("error" + t.getMessage());
}}
);
System.out.println("listenableFuture:" + listenableFuture.get());
}
其实除了JDK和Google有Future以外,Spring框架也提供一套Future.下面我们来看一个例子:
ListenableFuture<String> listenableFuture = asyncService.asynGet2();
SuccessCallback<String> successCallback = new SuccessCallback() {
@Override
public void onSuccess(Object result) {
System.out.println("异步回调success: result :"+result);
}
};
FailureCallback failureCallback = new FailureCallback() {
@Override
public void onFailure(Throwable ex) {
System.out.println("异步回调失败:"+ ex.getMessage());
}
};
listenableFuture.addCallback(successCallback,failureCallback);
Assert.assertEquals("123",listenableFuture.get());
asyncService 是一个异步Service类,ListenableFuture的返回类型必须通过 new AsyncResult<>()来返回方法的结果集:
new AsyncResult<>()