netty的eventLoop组件

本文深入解析Netty框架中的NioEventLoop组件,探讨其作为事件循环和线程执行器的角色,以及如何处理网络I/O和用户任务。通过分析NioEventLoop的实现机制,包括线程启动流程和任务执行策略,揭示Netty高性能网络编程的秘密。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

用最实用的NioEventLoop来看,其实,一个事件循环是一个内建selector的线程罢了,eventLoop是事件循环的意思,说明这个线程一直在执行,而且一直在循环的执行,知道外部给下下命令,让它停止。

基本的事件循环写法

  for(;;){

    //做一些事情

  }

最基本的写法。在循环里面,要处理网络读写,还有用户任务的处理,这里为什么要处理用户任务也放到事件循环里面来做呢?其实,大部分的用户任务依然是网络写,所以,在这里面合情合理。

NioEventLoop是当第一个任务投递进来,才进行真正的创建线程操作,在其父类SingleThreadEventExecutor当中的execute方法中可见:

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

        boolean inEventLoop = inEventLoop();
        addTask(task);
        if (!inEventLoop) {
            startThread();
            if (isShutdown()) {
                boolean reject = false;
                try {
                    if (removeTask(task)) {
                        reject = true;
                    }
                } catch (UnsupportedOperationException e) {
                    // The task queue does not support removal so the best thing we can do is to just move on and
                    // hope we will be able to pick-up the task before its completely terminated.
                    // In worst case we will log on termination.
                }
                if (reject) {
                    reject();
                }
            }
        }

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

这里的startThread方法就是真正启动线程的方法,如下所示:

   private void startThread() {
        if (state == ST_NOT_STARTED) {
            if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
                try {
                    doStartThread();
                } catch (Throwable cause) {
                    STATE_UPDATER.set(this, ST_NOT_STARTED);
                    PlatformDependent.throwException(cause);
                }
            }
        }
    }

可以发现,首先判断是否已经启动线程,若没有启动,则调用doStartThread方法,如下所示:

 private void doStartThread() {
        assert thread == null;
        executor.execute(new Runnable() {
            @Override
            public void run() {
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }

                boolean success = false;
                updateLastExecutionTime();
                try {
                    SingleThreadEventExecutor.this.run();
                    success = true;
                } catch (Throwable t) {
                    logger.warn("Unexpected exception from an event executor: ", t);
                } finally {
                    for (;;) {
                        int oldState = state;
                        if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
                                SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
                            break;
                        }
                    }

                    // Check if confirmShutdown() was called at the end of the loop.
                    if (success && gracefulShutdownStartTime == 0) {
                        if (logger.isErrorEnabled()) {
                            logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
                                    SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must " +
                                    "be called before run() implementation terminates.");
                        }
                    }

                    try {
                        // Run all remaining tasks and shutdown hooks.
                        for (;;) {
                            if (confirmShutdown()) {
                                break;
                            }
                        }
                    } finally {
                        try {
                            cleanup();
                        } finally {
                            // Lets remove all FastThreadLocals for the Thread as we are about to terminate and notify
                            // the future. The user may block on the future and once it unblocks the JVM may terminate
                            // and start unloading classes.
                            // See https://github.com/netty/netty/issues/6596.
                            FastThreadLocal.removeAll();

                            STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                            threadLock.release();
                            if (!taskQueue.isEmpty()) {
                                if (logger.isWarnEnabled()) {
                                    logger.warn("An event executor terminated with " +
                                            "non-empty task queue (" + taskQueue.size() + ')');
                                }
                            }
                            terminationFuture.setSuccess(null);
                        }
                    }
                }
            }
        });
    }

这里先判断,调用Executor的execute方法投递任务,这里是调用外部类的run方法,这里thread = Thread.currentThread()对thread成员变量进行了赋值。

 

这个NioEventLoop的写法确实跟我以前的写法不一样。在以前,如果我想让一个对象具有线程特性,成为一个主动对象,那么我会让这个类实现 Runnable接口,然后在一个方法内部创建线程,如下所示:

this.thread = new Thread(this);

this.thread.start();

这样的形式,单这里netty却不是,它使用了自己定义的io.netty.util.concurrent.ThreadPerTaskExecutor 类执行创建这个线程的工作,其实,NioEventLoop也是一个Executor,所以,你也能猜到了,这里用到了装饰器模式啦。

继承关系如下所示:

io.netty.util.concurrent.EventExecutorGroup

  io.netty.util.concurrent.EventExecutor

    io.netty.util.concurrent.AbstractEventExecutor

      io.netty.util.concurrent.AbstractScheduledEventExecutor

        io.netty.util.concurrent.SingleThreadEventExecutor

          io.netty.channel.SingleThreadEventLoop

            io.netty.channel.nio.NioEventLoop

可以看出,实现思路几个方面:

1.eventLoop可以提交任务,虽然eventLoop是单线程的,但是,我们要把它当做线程池来用。

2.eventLoop必须能够处理io任务

3.具有能够执行周期调度任务的能力,(延迟任务,固定周期执行任务),这样能够跟网络的异步操作特性相匹配,编程比较友好。

io.netty.util.concurrent.EventExecutor就是能够执行任务的接口类,是我们能够接触的最核心的类

 

稍后再完善。

转载于:https://www.cnblogs.com/weiguangyue/p/9879584.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值