Future & Promise
在异步处理时,常用到这两个接口
首先要说明 Netty 中的 Future 与 JDK 中的 Future 同名,但是是两个接口,Netty 的 Future 继承自 JDK 的 Future,而 Promise 又对 Netty Future 进行了扩展。
- JDK Future 只能同步等待任务结束(或成功、或失败)才能得到结果。
- Netty Future 可以同步等待任务结束得到结果,也可以异步方式得到结果,但都是要等任务结束。
- Netty Promise 不仅有 Netty Future 的功能,而且脱离了任务独立存在,只作为两个线程间传递结果的容器
功能/名称 | JDK Future | Netty Future | Netty Promise |
---|---|---|---|
cancel | 取消任务 | - | - |
isCancelled | 任务是否取消 | - | - |
isDone | 任务是否完成,不能区分任务成功或失败 | - | - |
get | 获取任务结果,阻塞等待 | - | - |
getNow | - | 获取任务结果,非阻塞,还未产生结果时返回 null | - |
await | - | 等待任务结束,如果任务失败,不会抛异常,而是通过 isSuccess 判断 | - |
sync | - | 等待任务结束,如果任务失败,抛出异常 | - |
isSuccess | - | 判断任务是否成功 | - |
cause | - | 获取失败信息,非阻塞,如果没有失败,返回 null | - |
addListener | - | 添加回调,异步接收结果 | - |
setSuccess | - | - | 设置成功结果 |
setFailure | - | - | 设置失败结果 |
1)JDK Future
Future 好比一个容器,比如你(一个线程)想让你的朋友(另一个线程)带点学习资料给你,朋友说你有没有U盘(Future 对象),我给装过来。你的朋友把学习资料(return 结果)转到了U盘里,第二天拿给你。你就可以从U盘中拿到学习资料了。Future 是被动的,是由执行任务的那个线程往里面填结果。
/**
* @desc
* @auth llp
* @date 2022/8/5 10:51
*/
@Slf4j
public class TestJskFuture {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 1、线程池
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
2,
2,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
// 2、提交任务
Future<Integer> future = poolExecutor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
log.debug("执行计算...");
TimeUnit.SECONDS.sleep(1);
return 50;
}
});
// 3、主线程通过 Future 来获取结果
log.debug("等待结果...");
log.debug("结果是 {}", future.get());
}
}
2)Netty Future
/**
* @desc
* @auth llp
* @date 2022/8/5 11:31
*/
@Slf4j
public class TestNettyFuture {
public static void main(String[] args) throws ExecutionException, InterruptedException {
NioEventLoopGroup group = new NioEventLoopGroup();
EventLoop eventLoop = group.next();
Future<Integer> future = eventLoop.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
log.debug("执行计算...");
TimeUnit.SECONDS.sleep(1);
return 50;
}
});
log.debug("等待结果...");
// 同步方式
// log.debug("结果是:{}", future.get());
// 异步方式
future.addListener(future1 -> log.debug("结果是:{}", future1.getNow()));
}
}
3)Netty Promise
通过以上两个例子 Future 都是由提交任务时返回创建的,被动的拿到 Future。不能够主动的创建。
/**
* @desc
* @auth llp
* @date 2022/8/5 11:40
*/
@Slf4j
public class TestNettyPromise {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 1、准备 EventLoop 对象
EventLoop eventLoop = new NioEventLoopGroup().next();
// 2、可以主动创建 Promise 创建
DefaultPromise<Integer> promise = new DefaultPromise<>(eventLoop);
new Thread(()->{
// 3、任意一个线程执行计算,计算完成之后向 promise 填充结果
log.debug("开始计算...");
try {
TimeUnit.SECONDS.sleep(1);
int i = 1 / 0; // 计算出现异常
promise.setSuccess(50);
} catch (InterruptedException e) {
e.printStackTrace();
promise.setFailure(e);
}
}).start();
// 4、接收结果的线程
log.debug("等待结果...");
log.debug("结果是:{}", promise.get());
// 异步
// promise.addListener(future -> log.debug("结果是:{}", future.get()));
}
}