其他分享
首页 > 其他分享> > 【Netty】NioEventLoop的启动(三):processSelectedKeys执行逻辑

【Netty】NioEventLoop的启动(三):processSelectedKeys执行逻辑

作者:互联网

回顾

如果忘记是怎么进入一下方法的,请回去看newChild章节

io.netty.channel.nio.NioEventLoop#run

...
// 检查I/O事件
select(wakenUp.getAndSet(false));
...
// 处理上面select查到的I/O事件
processSelectedKeys();
...
// 运行上面处理的事件集
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
...

上一节,简单走了走select方法,知道了select有阻塞和非阻塞两种方案,并且了解到Netty是如何解决jdk空轮询bug的。而这节就继续往下走,看看processSelectedKeys()方法的执行逻辑。

Netty Version:4.1.6


开始追踪

在追踪之前,先将视角拉回到io.netty.channel.nio.NioEventLoop#run(忘记的话看newChild那章),然后进入processSelectedKeys方法:
io.netty.channel.nio.NioEventLoop#processSelectedKeys

    private void processSelectedKeys() {
        if (selectedKeys != null) {
            processSelectedKeysOptimized(selectedKeys.flip());
        } else {
            processSelectedKeysPlain(selector.selectedKeys());
        }
    }

由于selectedKeys在没有连接的情况下仍不为Null,所以继续进入processSelectedKeysOptimized方法:
io.netty.channel.nio.NioEventLoop#processSelectedKeysOptimized

    private void processSelectedKeysOptimized(SelectionKey[] selectedKeys) {
        for (int i = 0;; i ++) {
            final SelectionKey k = selectedKeys[i];
            if (k == null) {
                break;
            }
            selectedKeys[i] = null;

            final Object a = k.attachment();

            if (a instanceof AbstractNioChannel) {
                processSelectedKey(k, (AbstractNioChannel) a);
            } else {
                @SuppressWarnings("unchecked")
                NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
                processSelectedKey(k, task);
            }

            if (needsToSelectAgain) {
                for (;;) {
                    i++;
                    if (selectedKeys[i] == null) {
                        break;
                    }
                    selectedKeys[i] = null;
                }

                selectAgain();
                selectedKeys = this.selectedKeys.flip();
                i = -1;
            }
        }
    }

进入processSelectedKey方法,由于代码很多,只贴一些关键的:
io.netty.channel.nio.NioEventLoop#processSelectedKey(java.nio.channels.SelectionKey, io.netty.channel.nio.AbstractNioChannel)

        final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
        if (!k.isValid()) {
            final EventLoop eventLoop;
            try {
                eventLoop = ch.eventLoop();
            } catch (Throwable ignored) {
                return;
            }
            if (eventLoop != this || eventLoop == null) {
                return;
            }
            // close the channel if the key is not valid anymore
            unsafe.close(unsafe.voidPromise());
            return;
        }
            int readyOps = k.readyOps();
            if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
                int ops = k.interestOps();
                ops &= ~SelectionKey.OP_CONNECT;
                k.interestOps(ops);

                unsafe.finishConnect();
            }

            if ((readyOps & SelectionKey.OP_WRITE) != 0) {
                ch.unsafe().forceFlush();
            }

            if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
                unsafe.read();
                if (!ch.isOpen()) {
                    return;
                }
            }

parentGroup和childGroup就是指ServerBootstrap中group方法绑定的两NioEventLoopGroup。


小结

chenwenjie2020 发布了22 篇原创文章 · 获赞 1 · 访问量 452 私信 关注

标签:NioEventLoop,Netty,SelectionKey,nio,unsafe,selectedKeys,processSelectedKeys,chan
来源: https://blog.csdn.net/qq_33347239/article/details/104126036