ListenableFuture

Future要获取异步任务执行的结果,需要通过轮询或者阻塞等待的方式,这样的方式,总显得不太“完美”,比较好的做法,应该是异步执行结束后,去通知用户异步任务结束了,你可以通过Future来获取执行结果了。

ListenableFuture 顾名思义可以监听Future,它是对java原生Future的扩展增强。我们知道Future表示一个异步计算任务,当任务完成时可以得到计算结果。如果我们希望一旦计算完就拿到结果展示给用户或者做另外的计算,就必须使用另一个线程不断的查询计算状态。这样做,代码复杂,而且效率底下。使用ListenableFuture guava帮我们检测Future是否完成了,如果完成了就自动调用回调函数,这样可以减少并发程序的复杂度。

public class AddTask implements Callable {

private int a,b;

public AddTask(int a, int b) {
    this.a = a;
    this.b = b;
}

public Integer call() throws Exception {
    return a+b;
}

public static void main(String[] args) throws InterruptedException, ExecutionException {
    ExecutorService executorService = Executors.newSingleThreadExecutor();

    Future future = executorService.submit(new AddTask(1,2));

    Thread.sleep(5000);

    //只有当future的状态是已完成时(future.isDone = true),get方法才会返回
    if(future.isDone()){
        System.out.println(future.get());
    }
}
}

对应JDK中的ExecutorService.submit(Callable)提交多线程异步运算的方式,guava提供了ListeningExecutorService接口,该接口返回ListenableFuture,而相应的Executor返回普通的Future。将ExecutorService转为ListeningExecutorService,可以使用MoreExecutors.listenintDecorator(ExecutorService)进行装饰。

ListeningExecutorService guavaExecutor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());

提交Callable任务

final ListenableFuture future =  pool.submit(new Callable() {
        @Override
        public String call() throws Exception {
            Thread.sleep(1000*3);
            return     "Task done !";
        }
    });

添加Listener

future.addListener(new Runnable() {
            @Override
            public void run() {
                try {
                    final String contents = future.get();
                    System.out.println(contents);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        }, MoreExecutors.sameThreadExecutor());

上面的代码,确实不怎么优雅,我们需要处理抛出的异常,需要自己通过future.get()获得前面计算的值。guava提供的一个简单方法如下:

Futures.addCallback(future, new FutureCallback() {
            @Override
            public void onSuccess(String result) {
                System.out.println(result);
            }

            @Override
            public void onFailure(Throwable t) {
                t.printStackTrace();
            }
        });

可以在成功和失败写相应的逻辑代码

你可能感兴趣的:(ListenableFuture)