Netty4.x源码分析之EventLoop(二)

本文深入分析了Netty的NioEventLoop事件循环,包括其启动过程、核心方法run的执行流程,以及如何处理I/O事件和任务队列。特别讨论了针对epoll空轮询CPU 100%问题的修复策略。通过对EventLoop的全面理解,揭示了Netty如何高效地管理I/O和任务执行。
摘要由CSDN通过智能技术生成

引言

在上篇文章我们分析了EventLoop的两大核心NioEventLoopGroup和NioEventLoop,NioEventLoopGroup在其父类MultithreadEventExecutor中维护了NioEventLoop数组,而NioEventLoop首先内部持有线程对象,所以NioEventLoopGroup是个线程池,并且上篇文章我们也分析了NioEventLoop除了是个单线程,并且也是它执行了I/O的事件循环,没错就是它自己的run方法里面的逻辑,今天我们专门深入到这块事件循环里面,看看Netty是怎么做的。

NioEventLoop事件循环

回顾一下上篇文章NioEventLoop启动是通过Channel注册到selector上时执行execute方法触发startThread()方法启动的。

@Override
    public void execute(Runnable task) {
        if (task == null) {
            throw new NullPointerException("task");
        }

        boolean inEventLoop = inEventLoop();
        if (inEventLoop) {
            addTask(task);
        } else {
            startThread();
            addTask(task);
            if (isShutdown() && removeTask(task)) {
                reject();
            }
        }

        if (!addTaskWakesUp && wakesUpForTask(task)) {
            wakeup(inEventLoop);
        }
    }

而这个startThread方法先是调用threadFactory创建一个线程,然后往线程提交一任务,而任务里面直接调用了NioEventLoop的run方法。

private void startThread() {
        if (state == ST_NOT_STARTED) {
            if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
                doStartThread();
            }
        }
    }

    private void doStartThread() {
        assert thread == null;
        executor.execute(new Runnable() {
            @Override
            public void run() {
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }
                try {
                    SingleThreadEventExecutor.this.run();
                    success = true;
                } catch (Throwable t) {
                    logger.warn("Unexpected exception from an event executor: ", t);
                    }
        });
    }
//删除无关代码

而这个run方法就是时间循环的核心,我们着重看看这个run方法。

protected void run() {
        for (;;) {
            try {
                switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                    case SelectStrategy.CONTINUE:
                        continue;
                    case SelectStrategy.SELECT:
                        select(wakenUp.getAndSet(false));

                        if (wakenUp.get()) {
                            selector.wakeup();
                        }
                    default:
                        // fallthrough
                }

                cancelledKeys = 0;
                needsToSelectAgain = false;
                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);
            }
        }
    }

可以看到run方法里面直接for (;;)一个忙循环开始一直保持这个Thread进行事件循环保证当前线程可以一直处理注册在当前线程的selector出来的I/O事件。接下来是个switch判断,我们来看看selectStrategy.calculateStrategy(selectNowSuppli

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值