Guava包中的ListenableFuture详情解析
来源:互联网 发布:日常悠哉大王知乎 编辑:程序博客网 时间:2024/06/05 14:30
前言:
本章介绍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
MoreExecutors.listeningDecorator(ExecutorService)
来进行装饰一下即可。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 或者canceledallAsList(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<>()
- Guava包中的ListenableFuture详情解析
- google Guava包的ListenableFuture解析
- google Guava包的ListenableFuture解析
- google Guava包的ListenableFuture解析
- Guava 中的 ListenableFuture
- guava中的ListenableFuture
- guava ListenableFuture
- guava ListenableFuture
- ListenableFuture in Guava
- guava ListenableFuture使用
- ListenableFuture in Guava
- Google Guava ListenableFuture入门
- Guava ListenableFuture 小试牛刀
- ListenableFuture in Guava
- ListenableFuture in Guava
- guava的ListenableFuture使用
- 多线程Future之Guava ListenableFuture
- Guava中并发ListenableFuture使用
- Android 关闭多个视图Intent.FLAG_ACTIVITY_CLEAR_TOP用法
- oracle自带表练习(二)
- CSRF攻击的对应方法
- 从哪6个方面能判断你具有成为管理者的潜力?
- 京东云主机使用-搭建简单网页(macOS)
- Guava包中的ListenableFuture详情解析
- Linux 利用UDEV服务解决RAC ASM存储设备名
- 面向对象。
- 白话原型和原型链
- 批量删除
- JavaScript基础系列之八 underscore
- CentOS 6.X安装dbproxy
- unregister_chrdev_region和__unregister_chrdev_region和cdev_del
- 类装载器详解