【Netty】GlobalEventExecutor源码个人见解

本文详细介绍了Netty中的GlobalEventExecutor类,它是一个单例线程池,用于调度监听器的执行。当任务提交到GlobalEventExecutor,如果1秒内没有新任务则线程会自动退出。文章通过分析源码揭示了其如何根据时间判断并创建新线程执行任务,以及如何控制线程的启动和停止。读者可以通过理解这个机制来更好地掌握Netty的并发处理。

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

一、背景

这几天在看netty的源码,在看如下位置的时候,看到了创建一个监听器,然后看到了DefaultPromise和GlobalEventExecutor这两个类

DefaultPromise看起来不会特别复杂,只是多了一些设置成功失败等方法,然后可以唤醒listener,做对应的处理,这里的用法,其实就是将监听器里执行的内容提交到GlobalEventExecutor这个类中做调用

大家可以搜索下相关文章看看DefaultPromise,这个类不是本文的重点

Netty 之 DefaultPromise 源码解析:https://www.jianshu.com/p/d46c9c70e0ba(作者:jijs)

     

 

二、GlobalEventExecutor

稍微介绍下这个类

这个类是一个单例,他会自动开启线程,如果1s内没有任务被阻塞或者队列中没有任务了就会自动结束线程,请注意,他不适合处理大量的task

netty这里使用他来调起listener(listener一般不会太多,而且也不会是很复杂的业务逻辑)

 

1、疑问

 

我看了一篇这样的文章:

Netty笔记-GlobalEventExecutor:https://blog.youkuaiyun.com/waterseason/article/details/86769956(转载)

主线程中,一次性添加多个任务,执行的线程都是同一个,但如果每隔1秒钟添加任务,就会看到线程都是新创建的,我挺好奇是怎么做到的,所以认真研究了下这个类的工作原理!

 

 

2、整体的运行流程

 

(1)、所以完整的情况是,当我在外面调用submit提交task到GlobalEventExecutor中


Future<Integer> future=GlobalEventExecutor.INSTANCE.submit(new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        System.out.println("eventExecutor threadId:"+Thread.currentThread().getId()+
                " inEventLoop:"+SelfGlobalEventExecutor.INSTANCE.inEventLoop());
        return 1;
    }
});

 

(2)、submit提交后,会调用到GlobalEventExecutor的execute方法

(3)、execute中会调用addTask(task),添加任务,并且判断inEventLoop,如果两个线程不一样的话(我在测试的时候,调用inEventLoop方法的都是main方法,和创建出来的thread方法都不是同一个),就会执行startThread(),创建新的线程

(4)、startThread方法会先判断started是否为false:

如果started为false就设置为true,然后通过threadFactory创建一个新的线程,并将taskRunner设置到新的线程中,最后调用线程的start方法

如果started为true,证明上一次创建的线程还在执行中,所以不需要做其他操作,等到之前那个线程拉取到新提交的task就可以

(5)、线程调用了start方法,就会调用TaskRunner内部类的run方法,run方法做了2件事情:

死循环通过takeTask这个方法中取出task,然后运行run,就会将队列中所有任务都拿出来执行

执行完当前所有task,将started设置为false,这样如果有新的task进来,就会新创建一个线程

(6)、takeTask这个方法里面也是一个死循环,但是里面有不少if和return

这里要说到,在初始化GlobalEventExecutor的时候,初始化了scheduledTaskQueue,并将quietPeriodTask放进去,通过这个来判断过了1s后,是否还有新的task(如何判断呢?请往下看)

(7)、如果takeTask方法中,没有从taskQueue里取出新的task了,那么就会调用fetchFromScheduledTaskQueue,将quietPeriodTask加入到taskQueue,并且被取出

(8)、然后在TaskRunner类中,由于task != quietPeriodTask,导致执行不了continue关键字,就会做后续的判断,将started设置为false,那么下次又有新的task来的时候,就会创建新的线程

 

3、回答疑问和总结

netty在父类的有序的Queue中,添加了一个1秒后到执行时间,并且每次执行间隔1秒,但是run方法里没有执行任何逻辑的ScheduledTask,并在takeTask方法中,拿到这个任务是否到执行时间,如果到了,直接poll任务,如果没到,就poll(超时时间)阻塞获取task任务,就是通过这样的方式来做那个1s的时间判断

如果想修改这个1s限制的话,就把如下的值改掉(比如改成10s)

那么10s内如果不停的有任务提交,执行的线程就不会停下来,就不会创建新的线程!

好厉害啊!感觉开眼了,我应该好好学习学习这些大佬写的代码~~

 

如果有同学想直接看源码的注释的话,可以参阅以下文章:

Netty源码分析-GlobalEventExecutor:https://blog.youkuaiyun.com/nimasike/article/details/102500491(作者:温故而知新666)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值