Netty源码解析(四) —— NioEventLoop处理io

本文深入探讨了Netty的NioEventLoop如何处理IO操作,包括轮询处理、空轮询问题的解决、任务调度以及读写事件的处理。通过分析`NioEventLoop.run`、`NioEventLoop.select`和`NioEventLoop.processSelectedKeys`等关键方法,揭示了Netty在处理网络连接和数据传输时的内部机制。
摘要由CSDN通过智能技术生成

NioEventLoop处理io的一些操作方法


io.netty.channel.nio.NioEventLoop#run

    /**
     * 启动服务  轮询selector
     */
    @Override
    protected void run() {
        for (;;) {
            try {
                switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                    case SelectStrategy.CONTINUE:
                        continue;
                    case SelectStrategy.SELECT:
                        // 重置 wakenUp 标记为 false
                        //wakenUp标识当前selector是否是唤醒状态
                        select(wakenUp.getAndSet(false));
                        if (wakenUp.get()) {
                            selector.wakeup();
                        }
                    default:
                }

                cancelledKeys = 0;
                needsToSelectAgain = false;
                final int ioRatio = this.ioRatio;
                if (ioRatio == 100) {
                    try {
                        //处理轮询到的key
                        processSelectedKeys();
                    } finally {
                        // Ensure we always run tasks.
                        //启动task
                        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) {
                ...
        }
    }

这个run方法是在NioEventLoop线程启动的时候调用的,这里面主要:

  1. 轮询准备好的key
  2. 处理轮训出来的key
  3. 运行task任务

io.netty.channel.nio.NioEventLoop#select

    /**
     * 轮询selector方法
     * @param oldWakenUp
     * @throws IOException
     */
    private void select(boolean oldWakenUp) throws IOException {
        Selector selector = this.selector;
        try {
            int selectCnt = 0;
            long currentTimeNanos = System.nanoTime();
            //delayNanos(currentTimeNanos)计算当前定时任务队列第一个任务的延迟时间
            //select的时间不能超过selectDeadLineNanos这个时间
            long selectDeadLineNanos = currentTimeNanos + delayNanos(currentTimeNanos);

            for (;;) {
                long timeoutMillis = (selectDeadLineNanos - currentTimeNanos + 500000L) / 1000000L;
                if (timeoutMillis <= 0) {
                    //如果超时  并且第一次轮询
                    //那么就再进行一次非阻塞的select 然后break结束轮询
                    if (selectCnt == 0) {
                        selector.selectNow();
                        selectCnt = 1;
                    }
                    break;
                }

                //nioEventLoop有任务在进行,那么就进行一次非阻塞的select 然后break结束轮询
                if (hasTasks() && wakenUp.compareAndSet(false, true)) {
                    selector.selectNow();
                    selectCnt = 1;
                    break;
                }

                //定时任务为空  截止时间没到,进行阻塞select
                int selectedKeys = selector.select(timeoutMillis);
                selectCnt ++;

                if (selectedKeys != 0 || oldWakenUp
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值