1 介绍
Future虽然为我们提供了一个凭据,但是在未来某个时间节点进行get()操作时仍然会使当前线程进入阻塞,显然这种操作方式并不是十分完美,因此在Google Guava并发包中提供了对异步任务执行的回调支持,它允许你注册回调函数而不用再通过get()方法苦苦等待异步任务的最终计算结果(Don’t Call Us, We’ll Call You!)
2 ListenableFuture(可监听的的Future)
Guava提供了ListneningExecutorService,使用该ExecutorService提交执行异步任务时将返回ListenableFuture,通过该Future,我们可以注册回调接口。
public interface ListeningExecutorService extends ExecutorService
示例代码:
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
// 通过 MoreExecutors定义ListeningExecutorService
ListeningExecutorService listeningDecorator = MoreExecutors.listeningDecorator(executorService);
// 提交任务
ListenableFuture<String> future = listeningDecorator.submit(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
});
// 注册监听
future.addListener(()->{
try {
// 获取任务结果
String res = future.get();
System.out.println("任务执行完毕,结果 -> " + res);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
},listeningDecorator);
}
3 FutureCallback
除了ListenableFuture之外,还可以注册FutureCallback,相比前者用Runnable接口作为回调接口,FutureCallback提供的回调方式则更为直观
示例:
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
// 通过 MoreExecutors定义ListeningExecutorService
ListeningExecutorService listeningDecorator = MoreExecutors.listeningDecorator(executorService);
// 提交任务
ListenableFuture<String> future = listeningDecorator.submit(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
});
// 注册callback
Futures.addCallback(future, new FutureCallback<String>() {
@Override
public void onSuccess(@Nullable String res) {
System.out.println("任务执行成功,结果是 ->" + res);
}
@Override
public void onFailure(Throwable throwable) {
System.out.println("任务执行失败");
}
},listeningDecorator);
}