Skip to content

Future&Promise

1. 概述

netty中的Future与jdk中的Future同名,但是是两个接口,netty的Future继承自jdk的Future,而Promise又对netty中的Future进行了扩展:

  • jdk Future只能同步等待任务结束(或成功、或失败)才能得到结果
  • netty Future可以同步等待任务结束得到结果,也可以异步方式得到结果,但都是要等任务结束
  • netty Promise不仅有netty Future的功能,而且脱离了任务独立存在,只作为两个线程间传递结果的容器
APIjdk Futurenetty FuturePromise
cancel取消任务--
isCanceled任务是否取消--
isDone任务是否完成,不能区分成功失败--
get获取任务结果,阻塞等待--
getNow-获取任务结果,非阻塞,还未产生结果时返回 null-
await-等待任务结束,如果任务失败,不会抛异常,而是通过 isSuccess 判断-
sync-等待任务结束,如果任务失败,抛出异常-
isSuccess-判断任务是否成功-
cause-获取失败信息,非阻塞,如果没有失败,返回null-
addLinstener-添加回调,异步接收结果-
setSuccess--设置成功结果
setFailure--设置失败结果

2. java的Future使用

java
public static void main(String[] args) throws ExecutionException, InterruptedException {
    Callable<Integer> callable = () -> {
        logger.info("开始执行任务");
        Thread.sleep(1000);
        return 1;
    };
    // 创建线程池使用callable接口
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    Future<Integer> future = executorService.submit(callable);
    Integer result1 = future.get();
    logger.info("计算结果:{}", result1);
}

运行结果:
Alt text

3. netty中Future使用

java
public static void main(String[] args) throws ExecutionException, InterruptedException {
    Callable<Integer> callable = () -> {
        logger.info("开始执行任务");
        Thread.sleep(1000);
        return 1;
    };
    NioEventLoopGroup group = new NioEventLoopGroup(2);
    Future<Integer> future = group.submit(callable);
    // 阻塞等待结果返回
    // Integer result1 = future.get();
    // 异步回调的方式得到结果
    future.addListener(new GenericFutureListener<Future<Integer>>() {

        @Override
        public void operationComplete(Future<Integer> future) throws Exception {
            Integer result = future.getNow();
            logger.info("计算结果:{}", result);
        }
    });
}

运行结果:
Alt text jdk中的Future和netty中的Future相同点是都不是我们直接创建的,而是通过方法返回的,除了创建还有结果的设置都是线程内部设置的,不对开发者开放。

4. netty中Promise使用

4.1 基本使用

java
public static void main(String[] args) throws ExecutionException, InterruptedException {
    EventLoop eventLoop = new DefaultEventLoopGroup().next();
    // 手动创建一个promise对象
    DefaultPromise<Integer> promise = new DefaultPromise<>(eventLoop);
    eventLoop.execute(() -> {
        logger.info("开始执行任务");
        try {
            Thread.sleep(3000);
            // 手动设置结果
            promise.setSuccess(99);
        } catch (InterruptedException e) {
            promise.setFailure(e);
        }
    });
    logger.info("start...");
    logger.info("计算结果:{}", promise.getNow()); // 还没有结果
    logger.info("计算结果:{}", promise.get());
    logger.info("任务执行完成");
}

运行结果如下: Alt text

4.2 使用await

java
public static void main(String[] args) throws ExecutionException, InterruptedException {
    EventLoop eventLoop = new DefaultEventLoopGroup().next();
    // 手动创建一个promise对象
    DefaultPromise<Integer> promise = new DefaultPromise<>(eventLoop);
    eventLoop.execute(() -> {
        logger.info("开始执行任务");
        try {
            Thread.sleep(3000);
            // 手动设置结果
            int i = 1 / 0;
            promise.setSuccess(99);
        } catch (Exception e) {// 需要把所有异常都捕获,避免直接抛出不走catch块
            promise.setFailure(e);
        }
    });
    logger.info("start...");
    promise.await(); // 同步阻塞但是不会抛出异常
    logger.info("等待结果...");
    logger.info("结果:{}", promise.getNow());
    // 通过判断拿结果
    logger.info("结果:{}", promise.isSuccess() ? promise.getNow() : promise.cause());
    logger.info("任务执行完成");
}

运行效果:
Alt text