netty源码阅读之NioEventLoop执行server channel注册与绑定任务。

源码阅读之NioEventLoop的执行server channel注册与绑定任务。

上一篇追到了server channel的初始化以及注册但没有真正的完成注册,只是将server channel 包装成一个task r然后推进队列中,接着启动了EventLoop下的线程。肯定是通过这线程从队列的另一端将task取出来执行,都是这么个套路,现在就继续跟下去看它真正完成注册。

SingleThreadEventExecutor类下的doStartThread方法

由于这个run方法是重写了SingleThreadEventExecutor类下面的run方法,在执行这个EventLoop子类的run的方法是因为没有发现有现成的线程,所以需要通过executor下面的线程工厂创建一个线程。

回顾一下 SingleThreadEventExecutor类下的doStartThread方法
1.在给EventLoop分配一个线程的时候,顺带将thread的引用保存下来,这个用于到IneventLoop方法中,被反复用于判断一个task是不是在当前EventLoop线程下执行。
2.接着SingleThreadEventExecutor.this.run()方法执行是调用NioEventLoop的run方法,到此EvenLoop的run方法就此不停地执行下去。

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_UPDATER.get(SingleThreadEventExecutor.this);
                        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) {
   
                        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 {
   
                            STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                            threadLock.release();
                            if (!taskQueue.isEmpty()) {
   
                                logger.warn(
                                        "An event executor terminated with " +
                                                "non-empty task queue (" + taskQueue.size() + ')');
                            }

                            terminationFuture.setSuccess(null);
                        }
                    }
                }
            }
        });
    }

NioEventLoop.run()方法

先上run方法的代码,这是一个死循环,反复从队列里轮询是否有可执行的任务。

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

                        // 'wakenUp.compareAndSet(false, true)' is always evaluated
                        // before calling 'selector.wakeup()' to reduce the wake-up
                        // overhead. (Selector.wakeup() is an expensive operation.)
                        //
                        // However, there is a race condition in this approach.
                        // The race condition is triggered when 'wakenUp' is set to
                        // true too early.
                        //
                        // 'wakenUp' is set to true too early if:
                        // 1) Selector is waken up between 'wakenUp.set(false)' and
                        //    'selector.select(...)'. (BAD)
                        // 2) Selector is waken up between 'selector.select(...)' and
                        //    'if (wakenUp.get()) { ... }'. (OK)
                        //
                        // In the first case, 'wakenUp' is set to true and the
                        // following 'selector.select(...)' will wake up immediately.
                        // Until 'wakenUp' is set to false again in the next round,
                        // 'wakenUp.compareAndSet(false, true)' will fail, and therefore
                        // any attempt to wake up the Selector will fail, too, causing
                        // the following 'selector.select(...)' call to block
                        // unnecessarily.
                        //
                        // To fix this problem, we wake up the selector again if wakenUp
                        // is true immediately after selector.select(...).
                        // It is inefficient in that it wakes up the selector for both
                        // the first case (BAD - wake-up required) and the second case
                        // (OK - no wake-up required).

                        if (wakenUp.get()) {
   
                            selector.wakeup();
                        }
                    default:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值