博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ListenalbeFuture的使用总结
阅读量:6952 次
发布时间:2019-06-27

本文共 4492 字,大约阅读时间需要 14 分钟。

为了提高任务处理速度,我们经常会将一些可并行处理的步骤用异步的方式去处理,如果想要获取异步计算的结果,在Java 8之前更多的用的是Future + Callable的方式来实现,下面是使用Future和Callable的一个demo,其中的是executor.submit()方法实际返回的就是FutureTask的实例,另外Future的get方法会一直阻塞直至获取结果。

public class FutureTest {    public static void main(String[] args) throws ExecutionException, InterruptedException {        ExecutorService executor = Executors.newSingleThreadExecutor();        Future
future = executor.submit(new MyCallable(3, 10)); // get方法会阻塞,直至获取结果 System.out.println(future.get()); executor.shutdown(); }}class MyCallable implements Callable
{ private int a; private int b; public MyCallable(int a, int b) { this.a = a; this.b = b; } @Override public Integer call() throws Exception { return a * b; }}复制代码

虽然Future已经相关方法提供了异步编程的能力,但是获取结果十分不方便,只能通过阻塞或者轮询的方式获取结果,阻塞的方式显然与我们异步编程的初衷相违背,而且轮询的方式也很消耗的CPU资源,计算结果也不能及时拿到。面对这种情况,为什么不采用一种类似观察者模式的方式,当结果结算完成后实时通知到监听任务呢?著名的guava包就提供了拓展Future,如ListenableFuture和SettableFuture,以及辅助类Futures。JDK 8中也提供类似ListenableFutureCompletableFuture接口,该接口包含很多api,后续的文章会逐一介绍。下面我们主要介绍一下Guava Future的使用。

引入Guava

最新版本的Guava可到中查找

com.google.guava
guava
23.0
复制代码

创建ListeningExecutorService

Guava为了支持自己的Listerner模式,新建了一种ExecutorService,叫做ListeningExecutorService,我们可以使用MoreExecutor创建它

// 创建一个由invoke线程执行的线程池 ListeningExecutorService executorService = MoreExecutors.newDirectExecutorService(); // 装饰自定义的线程池返回 ListeningExecutorService executorService1 = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());复制代码

线程池创建完毕后,我们就可以创建ListenableFuture

ListenableFuture
listenableFuture = executorService.submit(new MyCallable(3, 10));复制代码

添加监听(addListener)

ListenableFuture接口扩展自Future接口,并添加了一个新方法 addListener,该方法是给异步任务添加监听

listenableFuture.addListener(() -> {        System.out.println("listen success");        doSomeThing();    }, executorService);复制代码

添加回调(Futures.addCallBack)

addListener方法不支持获取返回值,如果需要获取返回值,可以使用Futures.addCallBack静态方法,该类是对JDK Future的拓展

// FutureCallback接口包含onSuccess()、onFailure()两个方法Futures.addCallback(listenableFuture, new FutureCallback() {    @Override    public void onSuccess(@Nullable Object result) {        System.out.println("res: " + result);    }    @Override    public void onFailure(Throwable t) {}}, executorService);复制代码

合并多个Future(Futures.allAsList)

如果需要同时获取多个Future的值,可以使用Futures.allAsList,需要注意的是如果任何一个Future在执行时出现异常,都会只执行onFailure()方法,如果想获取到正常返回的Future,可以使用Futures.successfulAsList方法,该方法会将失败或取消的Future的结果用null来替代,不会让程序进入onFailure()方法

ListenableFuture
future1 = executorService.submit(() -> 1 + 2);ListenableFuture
future2 = executorService.submit(() -> Integer.parseInt("3q"));ListenableFuture
> futures = Futures.allAsList(future1, future2);futures = Futures.successfulAsList(future1, future2);Futures.addCallback(futures, new FutureCallback
>() { @Override public void onSuccess(@Nullable List result) { System.out.println(result); } @Override public void onFailure(Throwable t) { t.printStackTrace(); }}, executorService);复制代码

返回值转换(Futures.transform)

如果需要对返回值做处理,可以使用Futures.transform方法,它是同步方法,另外还有一个异步方法Futures.transformAsync

// 原FutureListenableFuture
future3 = executorService.submit(() -> "hello, future");// 同步转换ListenableFuture
future5 = Futures.transform(future3, String::length, executorService);// 异步转换ListenableFuture
future6 = Futures.transformAsync(future3, input -> Futures.immediateFuture(input.length()), executorService);复制代码

immediateFuture和immediateCancelledFuture

immediateFuture该方法会立即返回一个待返回值的ListenableFutureimmediateCancelledFuture会返回一个立即取消的ListenableFuture,所以它返回的Future的isDone方法始终是false

JdkFutureAdapters

该方法可以将JDK Future转成ListenableFuture

Future
stringFuture = Executors.newCachedThreadPool().submit(() -> "hello,world");ListenableFuture
future7 = JdkFutureAdapters.listenInPoolThread(stringFuture);System.out.println(future7.get());复制代码

SettableFuture

SettableFuture可以认为是一种异步转同步工具,可以它在指定时间内获取ListenableFuture的计算结果

SettableFuture
settableFuture = SettableFuture.create();ListenableFuture
future11 = executorService.submit(() -> { int sum = 5 + 6; settableFuture.set(sum); return sum;});// get设置超时时间 System.out.println(settableFuture.get(2, TimeUnit.SECONDS));复制代码

原文地址:

转载于:https://juejin.im/post/5cb48bcd6fb9a0687015c9c7

你可能感兴趣的文章
结对编程讲义-PPT
查看>>
SOLR
查看>>
配置Nutch模拟浏览器以绕过反爬虫限制
查看>>
小牛电动的软文列表,和实际用户的反馈实在是天上地下。。
查看>>
list()详解
查看>>
mysql 修改编码 Linux/Mac/Unix/通用(杜绝修改后无法启动的情况!)
查看>>
IBM WebSphere MQ win 安装过程
查看>>
获取目录下子目录及文件的大小
查看>>
DNS服务器基本服务(正向、反向解析)、别名、递归、迭代、增量传输、完全传输...
查看>>
varchar nvarchar char nchar varchar2 nvarchar2
查看>>
js 百度地图 添加自定义控件
查看>>
AI考拉技术分享会--IDE 常用功能 for Node.js
查看>>
Tomcat session Error
查看>>
HAProxy双机高可用方案之HAProxy+Keepalived
查看>>
mysql忘记密码解决方法
查看>>
Eclipse安装m2eclipse插件(Maven)
查看>>
windows 下最快搭建svn服务器方法
查看>>
获取android系统外置存储卡路径的方法
查看>>
mysql 链接错误
查看>>
php 数组字符串搜索array_search技巧
查看>>