netty 之 异步处理双子星io.netty.util.concurrent.Future与io.netty.util.concurrent.Promise

一、JDK的Future

从这个类的注释中,我们可以了解到:

Future 类就是代表了异步计算的结果,这个接口的主要方法就是检查计算是否已完成,等待计算,然后返回计算结果。

当计算完成后,结果只能通过get方法返回;如果有必要会堵塞直到它计算完成。

可以通过cancel方法取消。增加的方法来判断任务是否正常完成或者被取消。一旦计算已经完成,计算不能被取消。

如果你想要使用Future 来取消,但是不提供一个可用的结果,你可以声明Futrue 的类型,但会返回null 作为一个基本任务的结果。

FutureTask 类是Futrue类的一个实现类,实现了Runnable接口,可以被Executor 执行。

二、JDK的FutureTask

  • 一个可取消的异步计算,这个类提供了对Future 的基本实现。有对计算的启动和取消方法,查询计算是否已完成,以及返回计算的结果。
  • 计算的结果只有在计算已完成后才能返回,如果计算没有完成,get方法会堵塞。一旦计算已经完成,计算不能被重启或取消。(除非计算是被runAndReset方法调用)
  • 可以看到这个类中有表示计算执行的状态
    private volatile int state;
    private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
    private static final int EXCEPTIONAL  = 3;
    private static final int CANCELLED    = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED  = 6;
  • 在判断当前计算是否已完成等状态时,都是通过这个字段来进行判断。

三、Netty的Future

1、说明

Netty的【Future】扩展了【java.util.concurrent.Future】:

  • 保留jdk Future的若干阻塞行为的接口
  • 同时增加了【listener类型的接口】,通过监听器可以让异步执行更加有效率(当异步执行有结果时进行回调)

2、Netty的Future继承体系与方法如下

四、Netty的io.netty.channel.ChannelFuture

netty的【ChannelFuture】又扩展了netty的【Future】

  • 提供和一个Channel进行绑定(通过ChannelFuture的channel方法可以获取对应的Channel对象)。
  • ChannelFuture的大部分接口都是Override的io.netty.channel.ChannelFuture
    • ①将类型具化成ChannelFuture
    • ②将参数GenericFutureListener的范型具化成   <? extends Future<? super Void>>,其中<? super Void>表示了一种没有返回值的异步调用:

4.1 ChannelFuture的状态

ChannelFuture有两种状态:未完成(uncompleted)和完成(completed).
当令Channel开始一个I/O操作时,会创建一个新的ChannelFuture去异步完成操作.
被创建时的ChannelFuture处于uncompleted状态(非失败,非成功,非取消);一旦ChannelFuture完成I/O操作,ChannelFuture将处于completed状态,结果可能有三种:

  1. 操作成功
  2. 操作失败
  3. 操作被取消(I/O操作被主动终止)
    需要关注ChannelFuture的其它属性来获取异常信息。

下图是 Netty API 中提供的ChannelFuture状态迁移图:

                                      +---------------------------+
                                      | Completed successfully    |
                                      +---------------------------+
                                 +---->      isDone() = true      |
 +--------------------------+    |    |   isSuccess() = true      |
 |        Uncompleted       |    |    +===========================+
 +--------------------------+    |    | Completed with failure    |
 |      isDone() = false    |    |    +---------------------------+
 |   isSuccess() = false    |----+---->      isDone() = true      |
 | isCancelled() = false    |    |    |       cause() = non-null  |
 |       cause() = null     |    |    +===========================+
 +--------------------------+    |    | Completed by cancellation |
                                 |    +---------------------------+
                                 +---->      isDone() = true      |
                                      | isCancelled() = true      |
                                      +---------------------------+

4.2 ChannelFutureListener监听接口

ChannelFuture的get()方法获取异步操作的结果,但是切记一定要设置超时时间
Netty建议通过ChannelFutureListener接口执行异步操作结束后的回调

示例代码:

 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg) {
     ChannelFuture future = ctx.channel().close();
     future.addListener(new ChannelFutureListener() {
         public void operationComplete(ChannelFuture future) {
             // Perform post-closure operation
             // ...
         }
     });
 }

 另外,ChannelFuture允许添加一个或多个(移除一个或多个)ChannelFutureListener监听接口,方法名:addListener(), addListeners(), removeListener(), removeListeners()

五、Netty的Promise

从Promise接口的方法上可以看出,其实Promise就是一个可写的Future,没有我想象的那么复杂.其实如果是理解了Future,那么Promise其实也是能够理解了.从它继承Future和添加的几个借口方法也能看出来它的大致用途。

1、说明

netty的【Promise】也扩展了netty的【Future】

  • 表示一种可写的Future:可以自定义设置异步执行的结果

 六、Netty的ChannelPromise

1、说明

netty的【ChannelPromise】也扩展了【Promise】、【ChannelFuture】

  • 绑定了Channel
  • 可以写异步执行结果
  • 具备【listener】功能

大部分方法都是Override父接口的方法:

  • 返回值声明成了具化的ChannelPromise类型
  • 参数GenericFutureListener的范型声明成了具化的:<? extends Future<? super Void>>

2、实现

DefaultChannelPromise是ChannelPromise的实现类,是实际运行时的Promise实例。

  • 继承体系中,DefaultChannelPromise与DefaultPromise分别负责对ChannelPromise的接口以及Promise的接口进行实现:
    • 比如:DefaultPromise中的对addListener方法的实现:
    @Override
    public Promise<V> addListener(GenericFutureListener<? extends Future<? super V>> listener) {
        checkNotNull(listener, "listener");

        synchronized (this) {
            addListener0(listener);
        }

        if (isDone()) {
            notifyListeners();
        }

        return this;
    }
    private void addListener0(GenericFutureListener<? extends Future<? super V>> listener) {
        if (listeners == null) {
            listeners = listener;
        } else if (listeners instanceof DefaultFutureListeners) {
            ((DefaultFutureListeners) listeners).add(listener);
        } else {
            listeners = new DefaultFutureListeners((GenericFutureListener<?>) listeners, listener);
        }
    }
    private void notifyListeners() {
        EventExecutor executor = executor();
        if (executor.inEventLoop()) {
            final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get();
            final int stackDepth = threadLocals.futureListenerStackDepth();
            if (stackDepth < MAX_LISTENER_STACK_DEPTH) {
                threadLocals.setFutureListenerStackDepth(stackDepth + 1);
                try {
                    notifyListenersNow();
                } finally {
                    threadLocals.setFutureListenerStackDepth(stackDepth);
                }
                return;
            }
        }

        safeExecute(executor, new Runnable() {
            @Override
            public void run() {
                notifyListenersNow();
            }
        });
    }
  • 可见,addListener方法中会先判断异步任务执行的状态isDone,如果异步任务执行完成就立即通知监听者,否则,加入监听者队列
  • 通知监听者就是找一个线程来执行调用监听者的回调函数
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值