当前位置: 首页 > news >正文

Netty源码分析(五):EventLoop

上一篇主要介绍了一下EventLoopGroup,本篇详细看下它的成员EventLoop

类结构

16a3b0a8a2ad9b33?w=843&h=805&f=jpeg&s=44271
NioEventLoop继承自SingleThreadEventLoop,而SingleThreadEventLoop又继承自SingleThreadEventExecutor
SingleThreadEventExecutor内部持有一个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, 有兴趣的童鞋可以关注一下。


本篇到此结束,如果读完觉得有收获的话,欢迎点赞、关注、加公众号【贰级天災】,查阅更多精彩历史!!!
169aa074c25481d1?w=258&h=258&f=jpeg&s=27967

转载于:https://www.cnblogs.com/YJTZ/p/10742949.html

相关文章:

  • 是时候放弃tensorflow集群投入horovod的怀抱
  • OO第二阶段作业总结
  • MUI 返回顶部
  • 知识点---js监听手机返回键,回到指定界面
  • 无论你是什么职业,这篇职场生存法则都是你必备的
  • 余莹是谁?
  • 37.C#--面对对象_类的基本使用
  • C++STL之vector用法总结
  • Angular-使用好NgForOf的trackBy带来性能上的提升
  • 微服务
  • 一篇文章告诉你Python上下文管理器怎么用
  • python算法之插入排序
  • swift学习笔记1
  • 关于可变参数varargs
  • Educational Codeforces Round 64 -C(二分)
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • 【剑指offer】让抽象问题具体化
  • 2017-09-12 前端日报
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • Bytom交易说明(账户管理模式)
  • JavaScript 基础知识 - 入门篇(一)
  • js操作时间(持续更新)
  • Just for fun——迅速写完快速排序
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • PHP CLI应用的调试原理
  • ReactNativeweexDeviceOne对比
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • supervisor 永不挂掉的进程 安装以及使用
  • tweak 支持第三方库
  • Twitter赢在开放,三年创造奇迹
  • Vue实战(四)登录/注册页的实现
  • 阿里云应用高可用服务公测发布
  • 笨办法学C 练习34:动态数组
  • 编写高质量JavaScript代码之并发
  • 高程读书笔记 第六章 面向对象程序设计
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 开源SQL-on-Hadoop系统一览
  • 强力优化Rancher k8s中国区的使用体验
  • 巧用 TypeScript (一)
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 翻译 | The Principles of OOD 面向对象设计原则
  • # include “ “ 和 # include < >两者的区别
  • # 透过事物看本质的能力怎么培养?
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • (C语言)fread与fwrite详解
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (四)图像的%2线性拉伸
  • (转)EXC_BREAKPOINT僵尸错误
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .NET delegate 委托 、 Event 事件,接口回调
  • .net 发送邮件
  • .NET导入Excel数据