Future和改进版的ListenableFutrue
这里只是通过两个非常简单的示例,说明一下这两个的区别。
一、Future
我们知道,通过Callable和Future接口创建的线程,可以获得返回值,同时也可以声明抛出异常。这就比Runnable提升了很多。
我们先看下面的例子:
/**
* @author lvxincao
* @Description Future的demo示例
* @Date 2021/1/26 17:08
* @Version V1.0
*/
public class Myfuture {
public static void main(String[] args) throws Exception{
FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("子线程名称:" + Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(10);
return "zhangsan";
}
});
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
System.out.println("我是主线程:"+Thread.currentThread().getName());
}
}
输出的结果如下:
子线程名称:Thread-0
zhangsan
我是主线程:main
这里我们看出一个问题,就是futureTask.get()获得返回值的方法,会阻塞主线程。这样的化,并不能充分发挥多线程的优势,更有些顺序执行的意思。那么怎么解决这个问题呢?
我们想,如果能够有一个线程来异步监听futureTask的结果,那么就不用阻塞主线程了。下面我们就看一下它的升级版:guava的ListenableFutrue。
二、ListenableFutrue
ListenableFuture和JDK原生Future最大的区别是前者做到了一个可以监听结果的Future。它可以监听异步执行的过程,执行完了,自动触发什么操作。除此之外,可以分别针对成功的情况,或者失败的情况做各种后续处理。
我们看下面的示例:
/**
* @author lvxincao
* @Description ListenableFutrues示例
* @Date 2021/1/26 16:55
* @Version V1.0
*/
public class MyListenableFutrue {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
ListenableFutureTask<String> stringListenableFutureTask = ListenableFutureTask.create(() -> {
System.out.println("子线程名称:" + Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(10);
return "zhangsan";
});
Futures.addCallback(stringListenableFutureTask, new FutureCallback<String>() {
@Override
public void onSuccess(@Nullable String s) {
System.out.println("成功:" + s);
}
@Override
public void onFailure(Throwable throwable) {
System.out.println("失败:");
}
}, Executors.newSingleThreadExecutor());
executorService.submit(stringListenableFutureTask);
System.out.println("我是主线程:" + Thread.currentThread().getName());
}
}
运行结果如下:
我是主线程:main
子线程名称:pool-1-thread-1
成功:zhangsan
我们看到,这时并没有出现主线程阻塞的情况。虽然如此,ListenableFutrue仍然存在缺陷,首先,写起来代码比较复杂繁琐;第二,它并没有解决多个异步任务需要相互依赖的场景。这就需要我们的java8中的CompletableFuture,我们后续会再进行详细的分析。