Netty笔记7:ChannelPromise通知处理

Netty笔记1:线程模型

Netty笔记2:零拷贝

Netty笔记3:NIO编程

Netty笔记4:Epoll

Netty笔记5:Netty开发实例

Netty笔记6:Netty组件

Netty笔记7:ChannelPromise通知处理

Netty笔记8:ByteBuf使用介绍

Netty笔记9:粘包半包

Netty笔记10:LengthFieldBasedFrameDecoder

Netty笔记11:编解码器

Netty笔记12:模拟Web服务器

Netty笔记13:序列化

文章目录


Netty中的操作都是异步的,它继承于 ChannelFuture,用于异步通知,如果我们要及时得到操作结果,该如何?

Netty在writeAndFlush时,会默认写入一个Promise(如果我们没有指定),位置:

io.netty.channel.AbstractChannelHandlerContext#writeAndFlush(java.lang.Object)

API如下:

public interface ChannelPromise extends ChannelFuture, Promise<Void> {

    // 返回管理的channel
    @Override
    Channel channel();

    // 这个方法可以忽略,void类型的结果是null
    @Override
    ChannelPromise setSuccess(Void result);

    // 设置异步操作成功
    ChannelPromise setSuccess();

    // 尝试设置成功,在没有设置过状态时,返回true,如果已经有状态返回false
    boolean trySuccess();

    // 设置失败状态,并可传入参数,描述失败原因
    @Override
    ChannelPromise setFailure(Throwable cause);

    // 下面的listener是状态变更的监听器
    // 通常可以通过这个监听器添加业务处理
    @Override
    ChannelPromise addListener(GenericFutureListener<? extends Future<? super Void>> listener);

    @Override
    ChannelPromise addListeners(GenericFutureListener<? extends Future<? super Void>>... listeners);

    // 移除监听器
    @Override
    ChannelPromise removeListener(GenericFutureListener<? extends Future<? super Void>> listener);

    @Override
    ChannelPromise removeListeners(GenericFutureListener<? extends Future<? super Void>>... listeners);

    // 用于阻塞当前线程,和 ChannelFuture 的一样
    @Override
    ChannelPromise sync() throws InterruptedException;

    // 中断当前线程,注意它并没抛出异常,需要Thread判断
    @Override
    ChannelPromise syncUninterruptibly();

    // 等待,直到IO操作完成
    @Override
    ChannelPromise await() throws InterruptedException;
    @Override
    ChannelPromise awaitUninterruptibly();

    /**
     * 返回一个新下ChannelPromise,判断isVoid,不理解
     */
    ChannelPromise unvoid();
}

不妨定义一个Handler测试一下:

public class ClientOutHandler extends ChannelOutboundHandlerAdapter {

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        // 运行时异常
        int i = 1/0;
        super.write(ctx, msg, promise);
    }
}

它的上一层是:io.netty.channel.AbstractChannelHandlerContext#invokeWrite0

    private void invokeWrite0(Object msg, ChannelPromise promise) {
        try {
            ((ChannelOutboundHandler) handler()).write(this, msg, promise);
        } catch (Throwable t) {
            notifyOutboundHandlerException(t, promise);
        }
    }

它最终会进入到notifyOutboundHandlerException,然后把异常设置到promise中:

    public static void tryFailure(Promise<?> p, Throwable cause, InternalLogger logger) {
        // 异常信息写入到Promise成功后,直接返回,不然就把信息打印出来
        if (!p.tryFailure(cause) && logger != null) {
            Throwable err = p.cause();
            if (err == null) {
                logger.warn("Failed to mark a promise as failure because it has succeeded already: {}", p, cause);
            } else if (logger.isWarnEnabled()) {
                logger.warn(
                        "Failed to mark a promise as failure because it has failed already: {}, unnotified cause: {}",
                        p, ThrowableUtil.stackTraceToString(err), cause);
            }
        }
    }

所以,我们需要稍微改一下:

// write时,直接newPromise()创建的promise,最后返回的,所以需要使用返回值才能正确添加监听器
ChannelFuture cf = future.channel().writeAndFlush(info);
// 这里使用write时返回promise对象
cf.addListener((ChannelFuture f)->{
    if (!f.isSuccess()) {
        System.out.println("写入失败!");
        f.cause().printStackTrace();
    }
});

上面我只是示例了一个异常的处理,它的作用是通知,可以在异步操作成功或失败时执行业务。

通过ChannelPromise的API可以知道,他可以实现成功、完成、可取消、已取消状态通知,也可以完成设置和其他一些功能。

image-20250304094145756

注意(总结)

我们执行异步操作时,需要对这个操作的结果或状态做出某些处理时,就需要对这个异步操作的Future增加监听器,然后参数是ChannelPromise,这个就是异步操作的通知对象。**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值