021 ListenableFuture

一 .概述

  在jdk之中,在1.5之后出现了Future接口,这个接口可以帮助我们完成异步任务结构的获取.

  我们首先看下接口的定义:

public interface Future<V> {
    // 取消任务
    boolean cancel(boolean mayInterruptIfRunning);
    // 判断任务是否被删除掉
    boolean isCancelled();
    // 判断任务是否完成
    boolean isDone();
    // 获取数据
    V get() throws InterruptedException, ExecutionException;
    // 给出指定的时间,获取数据
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

但是这个接口存在一个问题,就是在获取数据的时候一旦任务没有完成就会阻塞该方法.

  这样在一定的程度上,对并发的效果就是一种削弱.

在guava之中,出现了一种事件回调的方式,当我们的线程获取到执行的结果之后,就会自动帮助我们回调方法,这样就减少了我们对Future结构获取数据的阻塞.

public interface ListenableFuture<V> extends Future<V> {
 
  void addListener(Runnable listener, Executor executor);
}

通过上面的定义,我们ListenableFuture实际上继承了Future接口,并且添加了一个监听器,通过这种方式,我们就可以指定对应的回调.

通过调用ListenableFuture.addListener方法完成这个功能,这个方法使用Runnable实例和ExecutorService对象,ExecutorService可以是初始任务提交的相同Executor实例,或者完全是另外一个ExecutorService实例。

那么,我们怎么创建ListenableFuture对象呢?

  我们知道,Future对象一般情况下是由线程执行器对象通过submit()方法提交获得,而ListenableFuture就是通过一个包装的线程执行器创建出来的.

看下面的例子:  

public class ListenableFutureTest {

    public static void main(String[] args) {
        // 使用MoreExecutors包装器包装一个基本的Executor对象,我们就能获取到一个ListeningExecutorService对象
        ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(2));
        ListenableFuture<String> listenableFuture = executorService.submit(new Callable<String>() {

            @Override
            public String call() throws Exception {
                TimeUnit.SECONDS.sleep(3);
                return "trek";
            }
            
        });
        
        // 添加回调
        listenableFuture.addListener(new Runnable() {
            @Override
            public void run() {
                System.out.println("执行了回调的方法");
                executorService.shutdown();
            }
        }, executorService);
        
        System.out.println("主线程执行完毕");
    }
}

我们可以发现存在一个问题,那就是我们无法从ListenableFuture之中获取线程任务执行的结果.但是我们可以在线程任务执行完之后,进行另外一个线程任务的回调.

 

  

posted @ 2019-01-29 09:46  最爱五仁月饼  阅读(656)  评论(0编辑  收藏  举报