Netty源码分析(五):EventLoop

栏目: 编程工具 · 发布时间: 6年前

内容简介:与一个特定的线程进行了绑定,并且在其生命周期内,绑定的线程都不会再改变。从名字就可以看出来,
Netty源码分析(五):EventLoop
NioEventLoop 继承自 SingleThreadEventLoop ,而 SingleThreadEventLoop 又继承自 SingleThreadEventExecutorSingleThreadEventExecutor 内部持有一个Thread对象,是 Netty 多线程的基础。 可以认为, 一个 NioEventLoop

与一个特定的线程进行了绑定,并且在其生命周期内,绑定的线程都不会再改变。

SingleThreadEventExecutor

从名字就可以看出来, SingleThreadEventExecutor 是一个单线程事件执行器。主要做的事情就是线程的管理和事件的执行。

线程管理

SingleThreadEventExecutor 中定义了五种线程状态:

/**
     * 未开始
     */
    private static final int ST_NOT_STARTED = 1;
    /**
     * 已开始
     */
    private static final int ST_STARTED = 2;
    /**
     * 关闭中
     */
    private static final int ST_SHUTTING_DOWN = 3;
    /**
     * 已关闭
     */
    private static final int ST_SHUTDOWN = 4;
    /**
     * 已终止
     */
    private static final int ST_TERMINATED = 5;
复制代码

这几种状态对应的方法有 startThreadshutdownGracefullyshutdown

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);
                }
            }
        }
    }
复制代码

startThread 线程未开始时,尝试更新线程状态为一开始,更新成功,则调用 doStartThread 方法启动线程,子类的run方法就是在这里调用的,比如说接下来的 NioEventLoop

shutdownGracefully

public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
        // 静待时间需要>=0
        if (quietPeriod < 0) {
            throw new IllegalArgumentException("quietPeriod: " + quietPeriod + " (expected >= 0)");
        }
        // 超时时间不能小于静待时间
        if (timeout < quietPeriod) {
            throw new IllegalArgumentException(
                    "timeout: " + timeout + " (expected >= quietPeriod (" + quietPeriod + "))");
        }
        // 必须设置时间单位
        if (unit == null) {
            throw new NullPointerException("unit");
        }
        // 关闭中直接返回终止Future
        if (isShuttingDown()) {
            return terminationFuture();
        }
        boolean inEventLoop = inEventLoop();
        boolean wakeup;
        int oldState;
        for (; ; ) {
            // 关闭中直接返回终止Future
            if (isShuttingDown()) {
                return terminationFuture();
            }
            int newState;
            wakeup = true;
            oldState = state;
            if (inEventLoop) {
                newState = ST_SHUTTING_DOWN;
            } else {
                switch (oldState) {
                    case ST_NOT_STARTED:
                    case ST_STARTED:
                        newState = ST_SHUTTING_DOWN;
                        break;
                    default:
                        newState = oldState;
                        wakeup = false;
                }
            }
            if (STATE_UPDATER.compareAndSet(this, oldState, newState)) {
                break;
            }
        }
        gracefulShutdownQuietPeriod = unit.toNanos(quietPeriod);
        gracefulShutdownTimeout = unit.toNanos(timeout);
        if (oldState == ST_NOT_STARTED) {
            try {
                doStartThread();
            } catch (Throwable cause) {
                STATE_UPDATER.set(this, ST_TERMINATED);
                terminationFuture.tryFailure(cause);

                if (!(cause instanceof Exception)) {
                    PlatformDependent.throwException(cause);
                }
                return terminationFuture;
            }
        }
        if (wakeup) {
            wakeup(inEventLoop);
        }

        return terminationFuture();
    }
复制代码

shutdownGracefully 目的是让正在执行的任务再执行一会儿,同时拒绝新任务。 quietPeriodtimeout 这两个时间会在 confirmShutdown 方法中用到,当然单位已经转为纳秒了。

事件的执行

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);
        }
    }
复制代码

NioEventLoop

NioEventLoop 的核心操作都在它的run方法里面:

protected void run() {
        for (; ; ) {
            try {
                switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
                    case SelectStrategy.CONTINUE:
                        continue;
                    case SelectStrategy.SELECT:
                        // 重置wakenUp为false并选择任务
                        select(wakenUp.getAndSet(false));
                        if (wakenUp.get()) {
                            selector.wakeup();
                        }
                    default:
                }
                cancelledKeys = 0;
                needsToSelectAgain = false;
                final int ioRatio = this.ioRatio;
                // 当处理io用时占比为100%时
                if (ioRatio == 100) {
                    try {
                        processSelectedKeys();
                    } finally {
                        runAllTasks();
                    }
                } else {
                    final long ioStartTime = System.nanoTime();
                    try {
                        processSelectedKeys();
                    } finally {
                        final long ioTime = System.nanoTime() - ioStartTime;
                        runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
                    }
                }
            } catch (Throwable t) {
                // 处理Loop异常
                handleLoopException(t);
            }
            try {
                // 处于关闭状态
                if (isShuttingDown()) {
                    // 关闭所有
                    closeAll();
                    if (confirmShutdown()) {
                        return;
                    }
                }
            } catch (Throwable t) {
                // 处理Loop异常
                handleLoopException(t);
            }
        }
    }
复制代码

该方法主要是处理流程的控制,包括选择、处理和关闭这几种。

文中帖的代码注释全在: KAMIJYOUDOUMA , 有兴趣的童鞋可以关注一下。

本篇到此结束,如果读完觉得有收获的话,欢迎点赞、关注、加公众号【贰级天災】,查阅更多精彩历史!!!

Netty源码分析(五):EventLoop

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Beginning ASP.NET 4 in C# and Vb

Beginning ASP.NET 4 in C# and Vb

Imar Spaanjaars / Wrox / 2010-3-19 / GBP 29.99

This book is for anyone who wants to learn how to build rich and interactive web sites that run on the Microsoft platform. With the knowledge you gain from this book, you create a great foundation to ......一起来看看 《Beginning ASP.NET 4 in C# and Vb》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具