栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Netty原理五:ChannelFuture、DefaultChannelPromise对象解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Netty原理五:ChannelFuture、DefaultChannelPromise对象解析

文章目录
  • 1. 前言
  • 2. 原理解析
    • 2.1 ChannelFuture 调用 sync() 的作用
    • 2.2 Channel 调用的 closeFuture() 是什么

1. 前言

学习Netty的时候,大家肯定都会看到这么几句代码:

		//启动服务端监听
        ChannelFuture future = serverBootstrap.bind(7000).sync();
        //关闭?
        future.channel().closeFuture().sync();
  • 问题一:serverBootstrap.bind() 返回的对象是 ChannelFuture ,调用他的 sync() 方法有什么效果?
  • 问题二:channel.closeFuture().sync() 到底做了什么?

OK,带着这2个问题我们一步步解析

2. 原理解析 2.1 ChannelFuture 调用 sync() 的作用

服务单调用 bind 绑定端口的时候,会将 Channel 注册到 NioEventLoop,这时候会创建一个 DefaultChannelPromise 对象并返回

	//SingleThreadEventLoop.java
    public ChannelFuture register(Channel channel) {
        return register(new DefaultChannelPromise(channel, this));
    }

DefaultChannelPromise 和 ChannelFuture 之间存在继承关系:

前面的文章讲过,NioEventLoop 是一个单线程的线程池,整个注册都是通过异步线程处理的。因此我们大胆猜测:调用 sync() 是不是为了阻塞,等待注册结束?

看下 sync 的源码:

	//DefaultPromise.java
    public Promise sync() throws InterruptedException {
        await();
        rethrowIfFailed();
        return this;
    }

这里有个 await() ,翻译过来就是等待的意思,因此继续追踪:

  • isDone():每个 DefaultPromise 都有个 result 属性,用来标记当前对象的操作状态
  • wait():Object基类方法,如果 isDone() 返回 false,就使当前线程进入阻塞状态,知道其他线程调用 notify/notifyAll 唤醒

阻塞的地方找到了,那肯定有地方进行唤醒,答案就在 safeSetSuccess() 方法,该方法在注册成功后会被调用:

		//AbstractChannel.java
        protected final void safeSetSuccess(ChannelPromise promise) {
            if (!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) {
                logger.warn("Failed to mark a promise as success because it is done already: {}", promise);
            }
        }

这里有个 promise.trySuccess() ,底层会调用 setValue0 设置 result = SUCCESS,同时执行 notifyAll() 唤醒线程:

附上 checkNotifyWaiters 代码:

    private synchronized boolean checkNotifyWaiters() {
        if (waiters > 0) {
            notifyAll();
        }
        return listeners != null;
    }

总结: sync 会导致当前执行线程进入阻塞状态,直到异步线程调用 ChannelFuture 对象的 notify/notifyAll 进行唤醒,这一时机通常是在 ChannelFuture 表示的业务逻辑执行完毕后进行触发

2.2 Channel 调用的 closeFuture() 是什么

closeFuture() 返回的是 CloseFuture 类型对象,该对象是 Channel 的属性之一。

CloseFuture 继承 DefaultChannelPromise,它只有一个 setClosed() 方法,调用其他方法都会抛出异常:

    static final class CloseFuture extends DefaultChannelPromise {

        CloseFuture(AbstractChannel ch) {
            super(ch);
        }

        @Override
        public ChannelPromise setSuccess() {
            throw new IllegalStateException();
        }

        @Override
        public ChannelPromise setFailure(Throwable cause) {
            throw new IllegalStateException();
        }

        @Override
        public boolean trySuccess() {
            throw new IllegalStateException();
        }

        @Override
        public boolean tryFailure(Throwable cause) {
            throw new IllegalStateException();
        }

        boolean setClosed() {
            return super.trySuccess();
        }
    }

跟踪 setClosed 就可以发现,该方法在发生异常的时候调用,此时会将 closeFuture.sync() 导致的阻塞进行唤醒。

总结: closeFuture.sync() 是为了阻塞当前线程,避免程序直接结束掉而已

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/301468.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号