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的扩展方法。

接口:

传统JDK中的Future通过异步的方式计算返回结果:在多线程运算中可能或者可能在没有结束返回结果,Future是运行中的
线程的一个引用句柄,确保在服务执行返回一个Result。
ListenableFuture可以允许你注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用,  或者在运算(多线程执行)
完成后立即执行。这样简单的改进,使得可以明显的支持更多的操作,这样的功能在JDK concurrent包中的Future是不支持的。

  ListenableFuture 中的基础方法是addListener(Runnable, Executor) 该方法会在多线程运算完的时候,指定的Runnable参数传入的对象会被指定的Executor执行。

添加回调(Callbacks):

大多数用户喜欢使用Futures.addCallback(ListenableFuture<V>, FutureCallback<V>, Executor),或默认使用版本MoreExecutors.sameThreadExecutor()以便在回调快速轻便时使用。FutureCallback<V>实现两种方法:

  • onSuccess(V)在Future执行成功时去执行,取得成功的结果
  • onFailure(Throwable),在Future执行失败时去执行失败, 取得失败的结果

创建:

对应JDK的 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)将其转换FutureListenableFuture尽可能地采用修改原生的代码返回 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>接口 CheckedFutureListenableFuture,包含可以抛出被检查异常的多个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<>()




原创粉丝点击