文章目录
1. ListenableFuture是什么?
对原生JDKjava.util.concurrent.Future
的增强
原生Future
只提供了
- 阻塞等待结果
- 阻塞定时等待结果
- 取消
其实更好的方式是给future添加一个listener,成功或者异常后回调listener
ListenableFuture
就对原生的Future做了增强,提供了successCallback
和FailureCallback
ListenableFuture
诞生于Spring4.0,晚于jdk1.8
,当时并没有java.util.concurrent.CompletableFuture
这样更强大的Future
所以Spring创造了ListenableFuture
PS:
在Netty中也有一个可以监听的Future:io.netty.util.concurrent.Promise
,当时Netty4也晚于jdk1.8
在Spring团队后面创造的lettcue
(redis客户端)就大量地使用了CompletableFuture
2. 如何使用ListenableFuture
2.1 封装成ListenableFutureTask后提交给线程池
@Test
public void direct_use() throws Exception {
// 创建Task
ListenableFutureTask<Integer> task = new ListenableFutureTask<>(new CalculateTask(1, 2, Integer::sum));
// 添加回调
task.addCallback(new ListenableFutureCallback<Integer>() {
@Override
public void onFailure(Throwable ex) {
System.out.println("Calculate failed , error : " + ex);
}
@Override
public void onSuccess(Integer result) {
System.out.println("Calculate success , result : " + result);
}
});
// 创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(1);
// 提交任务
executorService.submit(task);
// 关闭线程池
executorService.shutdownNow();
executorService.awaitTermination(1, TimeUnit.MINUTES);
}
private static class CalculateTask implements Callable<Integer> {
private final int x;
private final int y;
private final BiFunction<Integer, Integer, Integer> operate;
public CalculateTask(int x, int y, BiFunction<Integer, Integer, Integer> operate) {
this.x = x;
this.y = y;
this.operate = operate;
}
@Override
public Integer call() throws Exception {
TimeUnit.SECONDS.sleep(1);
return operate.apply(x, y);
}
}
2.2 使用spring的AsyncListenableTaskExecutor
这个线程池定义了两个方法返回ListenableFuture
ListenableFuture<?> submitListenable(Runnable task);
<T> ListenableFuture<T> submitListenable(Callable<T> task);
@Test
public void listenable_task_executor() throws Exception {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 提交任务
ListenableFuture<Integer> task = executor.submitListenable(new CalculateTask(1, 0, Integer::divideUnsigned));
// 添加回调
task.addCallback(new ListenableFutureCallback<Integer>() {
@Override
public void onFailure(Throwable ex) {
System.out.println("Calculate failed , error : " + ex);
}
@Override
public void onSuccess(Integer result) {
System.out.println("Calculate success , result : " + result);
}
});
// 关闭线程池
executor.setAwaitTerminationSeconds(10);
executor.shutdown();
}
3. 一点小建议
什么情况下该使用ListenableFuture
- jdk < 1.8时,因为
CompletableFuture
是jdk1.8
才被创造的 - 场景较为简单时,只是需要简单的回调,
ListenableFuture
相比较CompletableFuture
更易读,更简洁
其他情况下都更推荐使用CompletableFuture
,因为功能非常强大,性能也很优秀,Doug Lea大神对其的优化无所不用其极。