千家信息网

NioEventLoop的run方法实例分析

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要介绍了NioEventLoop的run方法实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇NioEventLoop的run方法实例分析文章都会有所收获,
千家信息网最后更新 2026年11月01日NioEventLoop的run方法实例分析

这篇文章主要介绍了NioEventLoop的run方法实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇NioEventLoop的run方法实例分析文章都会有所收获,下面我们一起来看看吧。

Netty事件循环主逻辑

Netty 事件循环主逻辑在 NioEventLoop.run 中的 processSelectedKeys函数中

protected void run() {      //主循环不断读取IO事件和task,因为 EventLoop 也是 juc 的 ScheduledExecutorService 实现        for (;;) {            try {                switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {                    case SelectStrategy.CONTINUE:                        continue;                    case SelectStrategy.SELECT:                        select(wakenUp.getAndSet(false));                                                if (wakenUp.get()) {                            selector.wakeup();                        }                        // fall through                    default:                }                cancelledKeys = 0;                needsToSelectAgain = false;            // IO事件占总执行时间的百分比 */                final int ioRatio = this.ioRatio;                if (ioRatio == 100) {                    try {                        processSelectedKeys();                    } finally {                        // Ensure we always run tasks.                        runAllTasks();                    }                } else {                    final long ioStartTime = System.nanoTime();                    try {                        processSelectedKeys();                    } finally {                        // Ensure we always run tasks.                        final long ioTime = System.nanoTime() - ioStartTime;                        runAllTasks(ioTime * (100 - ioRatio) / ioRatio);                    }                }            } catch (Throwable t) {                handleLoopException(t);            }            // Always handle shutdown even if the loop processing threw an exception.            try {                if (isShuttingDown()) {                    closeAll();                    if (confirmShutdown()) {                        return;                    }                }            } catch (Throwable t) {                handleLoopException(t);            }        }    }

processSelectedKeys 函数 执行时会判断是否执行优化的版本,即判断 SelectedSelectionKeySet 是否为空。

是否开启优化取决于是否设置了环境变量 io.netty.noKeySetOptimization ,默认是 false 代表开启

private static final boolean DISABLE_KEYSET_OPTIMIZATION =            SystemPropertyUtil.getBoolean("io.netty.noKeySetOptimization", false);

原理是通过反射的方式设置 eventLoop绑定的selector中的 selectKeys属性 为 SelectedSelectionKeySet ,好处是不用 迭代 selector.selectedKeys()

初始化 EventLoop

注入时机为初始化 EventLoop 的时候

private SelectorTuple openSelector() {        12      //注入逻辑40         Object maybeException = AccessController.doPrivileged(new PrivilegedAction() {            @Override            public Object run() {                try {                    Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");                    Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");                    Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField);                    if (cause != null) {                        return cause;                    }                    cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField);                    if (cause != null) {                        return cause;                    }                    selectedKeysField.set(unwrappedSelector, selectedKeySet);                    publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);                    return null;                } catch (NoSuchFieldException e) {                    return e;                } catch (IllegalAccessException e) {                    return e;                }            }        });        ........78     }

处理读事件

处理读事件主要在processSelectedKey 中 ,分别对 读、写、连接事件进行了处理。

private void processSelectedKeysOptimized() {        for (int i = 0; i < selectedKeys.size; ++i) {            final SelectionKey k = selectedKeys.keys[i];            // null out entry in the array to allow to have it GC'ed once the Channel close            // See https://github.com/netty/netty/issues/2363            selectedKeys.keys[i] = null;            final Object a = k.attachment();            if (a instanceof AbstractNioChannel) {                //分别处理每个channel的事件                processSelectedKey(k, (AbstractNioChannel) a);            } else {                @SuppressWarnings("unchecked")                NioTask task = (NioTask) a;                processSelectedKey(k, task);            }            if (needsToSelectAgain) {                // null out entries in the array to allow to have it GC'ed once the Channel close                // See https://github.com/netty/netty/issues/2363                selectedKeys.reset(i + 1);                selectAgain();                i = -1;            }        }    }    private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {        final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();        if (!k.isValid()) {            final EventLoop eventLoop;            try {                eventLoop = ch.eventLoop();            } catch (Throwable ignored) {                // If the channel implementation throws an exception because there is no event loop, we ignore this                // because we are only trying to determine if ch is registered to this event loop and thus has authority                // to close ch.                return;            }            // Only close ch if ch is still registered to this EventLoop. ch could have deregistered from the event loop            // and thus the SelectionKey could be cancelled as part of the deregistration process, but the channel is            // still healthy and should not be closed.            // See https://github.com/netty/netty/issues/5125            if (eventLoop != this || eventLoop == null) {                return;            }            // close the channel if the key is not valid anymore            unsafe.close(unsafe.voidPromise());            return;        }        try {            int readyOps = k.readyOps();            // We first need to call finishConnect() before try to trigger a read(...) or write(...) as otherwise            // the NIO JDK channel implementation may throw a NotYetConnectedException.            if ((readyOps & SelectionKey.OP_CONNECT) != 0) {                // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking                // See https://github.com/netty/netty/issues/924                int ops = k.interestOps();                ops &= ~SelectionKey.OP_CONNECT;                k.interestOps(ops);          //处理了连接事件                unsafe.finishConnect();            }            // Process OP_WRITE first as we may be able to write some queued buffers and so free memory.            if ((readyOps & SelectionKey.OP_WRITE) != 0) {                // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
 //将要写入的buffer flush掉          ch.unsafe().forceFlush();            }            // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead            // to a spin loop            if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {           //回调 pipeline 上所有的 ChannelInboundHandler 的 fireChannelRead  和 channelReadComplete 函数                unsafe.read();            }        } catch (CancelledKeyException ignored) {            unsafe.close(unsafe.voidPromise());        }    }

注意

NioServerSocketChannel 和 NioSocketChannel 都是 同样的 处理逻辑, 不同的是 前者 只关注 OP_ACCEPT 和 OP_READ事件, 后者 关注 OP_READ、OP_WRITE、OP_CONNECT事件

当NioServerSocketChannel 发生 OP_ACCEPT事件时 会 触发

AbstractNioChannel.NioUnsafe.read -> NioSctpServerChannel.doReadMessages(List) -> ServerBootstrapAcceptor.channelRead ,

将受到的 NioSocketChannel 注册到 childEventLoop 。

关于"NioEventLoop的run方法实例分析"这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对"NioEventLoop的run方法实例分析"知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。

事件 处理 实例 实例分析 方法 分析 逻辑 函数 知识 循环 内容 篇文章 不同 循环不断 不断 不用 代表 价值 原理 取决于 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 科技和互联网公司 互联网电商科技 互联网科技公司电话 有马互联网科技 华中科技大学互联网 互联网科技宣传片 深圳互联网科技怎么样 海南科技产业互联网平台 深圳前海聚择互联网科技有限公司 随着互联网科技发展 阿里互联网科技公司 世界互联网领先科技成果获奖 广东工业互联网大赛深圳学泰科技 江苏互联网智能科技软件 互联网的科技体现在哪里 互联网科技创新创业项目 互联网企业和网络科技有限公司 伍佰万互联网科技是干嘛的 六子台科技互联网展会 小牛互联网科技有限公司地址 互联网科技公司排名 天津市摩尔互联网科技 互联网科技媒体 哈尔滨秒房互联网科技有限公司 移动互联网科技股 互联网科技的全部知识 徐州市互联网科技有限公司 烟台灵鸽互联网科技有限公司 上海科技产业互联网平台 锡山区互联网智能科技产品供应
0