//测试Guave版本,测试是最高版本28.1
<!-- guava 最新版本28.1-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.1-jre</version>
<!-- <version>26.0-jre</version>-->
</dependency>
ListenableFuture简单应用
Guava的ListenableFuture是对多线程使用的一个很好的补充,通过ListenableFuture的addCallback我们可以很好的完成调用成功(onSuccess)或者失败(onFailure)以后的逻辑处理,使用方法如下:
@Slf4j
public class ListenableFutureDemo implements Callable<String>{
String info;
public ListenableFutureDemo(String info) {
this.info = info;
}
public static void main(String[] args) {
log.info("线程{}, 主线程开始---" , Thread.currentThread().getName());
ExecutorService pool = Executors.newFixedThreadPool(10);
//将java的包装成Listenable的线程池 Guava提供的返回值是ListenableFuture的线程池
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(pool);
ListenableFuture<String> future1 = executorService.submit(new ListenableFutureDemo("昨夜西风凋碧树"));
ListenableFuture<String> future2 = executorService.submit(new ListenableFutureDemo("独上高楼"));
//ListenableFuture可以设置callBack addCallback在addListener基础上封装;
//在线程执行成和执行失败的策略;设置线程池异步执行callback、不然就是同步执行
Futures.addCallback(future1, new CallBackDemo(), MoreExecutors.directExecutor());
Futures.addCallback(future2, new CallBackDemo(), pool);
log.info("主线程结束");
}
@Override
public String call() throws Exception {
log.info("线程{}, 工作线程执行完成:{}" , Thread.currentThread().getName(), info);
if(true){
throw new RuntimeException("我执行失败了");
}
return info;
}
}
@Slf4j
class CallBackDemo implements FutureCallback<String> {
@Override
public void onSuccess(@NullableDecl String o) {
log.info("线程{}, callback成功响应开始:{}" , Thread.currentThread().getName(), o);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("线程{}, callback成功响应结束:{}" , Thread.currentThread().getName(), o);
}
@Override
public void onFailure(Throwable throwable) {
log.info("线程{}, callback失败响应:{}" , Thread.currentThread().getName());
}
}
根据上面代码我们可以看到,关键类如下:
MoreExecutors:该类是final类型的工具类,提供了很多静态方法。比如ListeningDecorator方法将java线程池装饰为ListeningExecutorService,使用此实例submit方法即可初始化ListenableFuture对象。
ListeningExecutorService:该类是对ExecutorService的扩展,重新ExecutorService类中的submit方法,返回ListenableFuture对象。
ListenableFuture:该接口扩展了Future接口,增加了addListener方法,该方法在给定的executor上注册一个监听器,当计算完成时会马上调用该监听器。不能够确保监听器执行的顺序,但可以在计算完成时确保马上被调用。addListener和addCallback本质是一样的,addCallback是在addListener的基础上做了封装。
FutureCallback:该接口提供了OnSuccess和OnFailure方法。获取异步计算的结果并回调。
Futures:该类提供了很多实用的静态方法以供实用。设置同步执行回调还是异步执行回调
ListenableFutureTask:该类扩展了FutureTask类并实现了ListenableFuture接口,增加了addListener方法。
///将一个 ExecutorService 转换为 ListeningExecutorService,MoreExecutors装饰
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
//Guava提供两个callBack用于ListenableFuture回调,高版本已经去掉第二个方法
Futures.addCallback(ListenableFuture<V> future, FutureCallback<? super V> callback, Executor executor);
Futures.addCallback(ListenableFuture<V> future, FutureCallback<? super V> callback);
// 但是你可以继续设置当前线程
MoreExecutors.directExecutor()
SettableFuture简单介绍
@Slf4j
public class SettableFutureDemo implements Callable<String> {
static ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
public static void main(String[] args) {
testSettableFuture(); //规定时间拿到结果;适合需要在规定时间拿结果的应用;指定时间拿不到结果抛出异常
}
//如果执行任务线程超时,并不会中断执行;set完成后即可拿到响应结果
public static void testSettableFuture(){
SettableFuture<String> settableFuture = SettableFuture.create();
ListenableFuture<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(5);
settableFuture.set("得到世界");
log.info("会继续走下去么??");
return "测试";
}
});
try {
Futures.addCallback(future, new FutureCallback<String>() {
@Override
public void onSuccess(@Nullable String result) {
log.info("执行成功响应:{}", result);
}
@Override
public void onFailure(Throwable th) {
log.error("执行失败", th);
}
} ,executorService);
log.info("settableFuture 规定时间检测:" + settableFuture.get(2, TimeUnit.SECONDS));
// set完成后即可拿到响应结果
//log.info("settableFuture 规定时间检测:" + settableFuture.get(10, TimeUnit.SECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
}
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(2);
return "测试";
}
}
SettableFuture: 适合规定时间拿到SettableFuture set值;Set结果后即可返回、响应
适合在规定时间拿到结果的应用;规定时间没拿到就报错;
但是注意当前任务执行线程会继续执行,OnSuccess也会成功执行
Futures简介
@Slf4j
public class FuturesMethodDemo {
static ExecutorService pool = Executors.newFixedThreadPool(5);//定义线程数
/**
* Futures相关
**/
//对多个结果进行处理
//allAsList:对多个ListenableFuture的合并,返回一个当所有Future成功时返回多个Future返回值组成的List对象。注:当其中一个Future失败或者取消的时候,将会进入失败或者取消。
//successfulAsList:和allAsList相似,唯一差别是对于失败或取消的Future返回值用null代替。不会进入失败或者取消流程。
//Futures.transform:对于ListenableFuture的返回值进行转换。
//immediateFuture/immediateCancelledFuture: 立即返回一个待返回值的ListenableFuture。
//将ListenableFuture 转换成CheckedFuture。CheckedFuture 是一个ListenableFuture ,其中包含了多个版本的get 方法,方法声明抛出检查异常.这样使得创建一个在执行逻辑中可以抛出异常的Future更加容易
//JdkFutureAdapters.listenInPoolThread(future): guava同时提供了将JDK Future转换为ListenableFuture的接口函数。
// ThreadFactoryBuilder 方便的threadFactory--- 可以了解下threadFactory
//ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("测试").build();
public static void main(String[] args) {
List<String> list = createTickets();//获取车票
List<ListenableFuture<Integer>> futures = Lists.newArrayList();
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(pool);
for (int i = 0; i < list.size(); i++) {
futures.add(executorService.submit(new Task(list.get(i))));
}
//testAsList(futures);
transforResult(testAsList(futures));
pool.shutdown();
}
public static ListenableFuture<List<Integer>> testAsList(List<ListenableFuture<Integer>> futures) {
/** successfulAsList和allAsList **/
//allAsList:对多个ListenableFuture的合并,返回一个当所有Future成功时返回多个Future返回值组成的List对象。注:当其中一个Future失败或者取消的时候,将会进入失败或者取消
//ListenableFuture<List<Integer>> resultsFuture = Futures.allAsList(futures);
//successfulAsList:和allAsList相似,唯一差别是对于失败或取消的Future返回值用null代替。不会进入失败或者取消流程。
ListenableFuture<List<Integer>> resultsFuture = Futures.successfulAsList(futures);
try {
//所有都执行完毕
List<Integer> integers = resultsFuture.get();
log.info("结果:" + integers.stream().map(i -> i + "").collect(Collectors.joining(",")));
} catch (Exception e) {
log.error("出错了", e);
} finally {
log.info("操作完毕");
}
return resultsFuture;
}
//将所有的结果,好分割,输出字符串 立即返回一个待返回值的ListenableFuture。
public static void transforResult(ListenableFuture<List<Integer>> resultsFuture) {
/** AsyncFunction和 immediateFuture **/
ListenableFuture<String> transformAsync = Futures.transformAsync(resultsFuture, new AsyncFunction<List<Integer>, String>() {
@Override
public ListenableFuture<String> apply(@NullableDecl List<Integer> result) throws Exception {
return Futures.immediateFuture(result.stream().map(i -> i + "").collect(Collectors.joining(",")));
}
}, pool);
try {
log.info("转换后的结果{}", transformAsync.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public static List<String> createTickets() {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add("车票" + i);
}
return list;
}
}
@Slf4j
class Task implements Callable<Integer> {
private String ticket;
public Task(String ticket) {
this.ticket = ticket;
}
@Override
public Integer call() throws Exception {
if (ticket.equals("车票5")) {
throw new Exception();
}
log.info("已卖" + ticket);
return 1;
}
}
Futures.allAsList():将ListenableFuture集合结果合并处理;
如果其中一个futures失败报错,执行get获取结果是会报错
Futures.successfulAsList:同allAsList类似,但是会将执行失败的future结果替换为null;
执行get获取结果时不会失败
Futures.transform/:对于ListenableFuture的返回值进行转换。
transformAsync 同上
immediateFuture/immediateCancelledFuture: 立即返回一个待返回值的ListenableFuture