简介

在netty中不管是服务器端的ServerBootstrap还是客户端的Bootstrap,在创建的时候都需要在group方法中传入一个EventLoopGroup参数,用来处理所有的ServerChannel和Channel中所有的IO操作和event。

可能有的小伙伴还稍微看了一下netty的源码,可能会发现还有一个和EventLoopGroup非常类似的类叫做EventLoop。那么EventLoopGroup和EventLoop有什么关系呢?他们的底层和channel的交互关系是怎么样的呢?一起来看看吧。

EventLoopGroup和EventLoop

EventLoopGroup继承自EventExecutorGroup:

public interface EventLoopGroup extends EventExecutorGroup

在前面的文章中我们讲过,EventExecutorGroup中有一个next方法可以返回对应的EventExecutor,这个方法在EventLoopGroup中进行了重写:

    EventLoop next();

next方法返回的不再是一个EventExecutor,而是一个EventLoop。

事实上,EventLoop和EventLoopGroup的关系与EventExecutor和EventExecutorGroup的关系有些类似,EventLoop也是继承自EventLoopGroup,EventLoopGroup是EventLoop的集合。

public interface EventLoop extends OrderedEventExecutor, EventLoopGroup

在EventLoopGroup中,除了重写的next方法之外,还添加了channel的注册方法register,用于将channel和注册到EventLoop中,从而实现channel和EventLoop的绑定。

ChannelFuture register(Channel channel);

在EventLoop中,自多添加了一个parent方法,用来表示EventLoop和EventLoopGroup的关联关系:

EventLoopGroup parent();

EventLoopGroup在netty中的默认实现

EventLoopGroup在netty中的默认实现叫做DefaultEventLoopGroup,先来看一下它的继承关系:

如果看了之前我讲解的关于EventExecutorGroup的朋友可以看出来,DefaultEventLoopGroup和DefaultEventExecutorGroup的继承关系是很类似的,DefaultEventLoopGroup继承自MultithreadEventLoopGroup,而MultithreadEventLoopGroup又继承自MultithreadEventExecutorGroup并且实现了EventLoopGroup接口:

public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup

MultithreadEventLoopGroup是用多线程来处理Event Loop。

在MultithreadEventLoopGroup中定义了一个DEFAULT_EVENT_LOOP_THREADS来存储默认的处理Event Loop线程的个数:

DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));

对于EventLoopGroup中新加的几个register方法,MultithreadEventLoopGroup都是调用对应的next方法来实现的:

public ChannelFuture register(Channel channel) {
return next().register(channel);
}

这里的next()方法的实现实际上调用的是父类的next方法,也就是MultithreadEventExecutorGroup中的next方法,来选择Group管理的一个EventLoop:

public EventLoop next() {
return (EventLoop) super.next();
}

对于DefaultEventLoopGroup来说,它继承自MultithreadEventLoopGroup,实现了一个newChild方法,用来将传入的executor封装成为EventLoop:

    protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new DefaultEventLoop(this, executor);
}

EventLoop在netty中的默认实现

EventLoop在netty中的默认实现叫做DefaultEventLoop,先来看下它的继承关系:

DefaultEventLoop继承自SingleThreadEventLoop,而SingleThreadEventLoop又继承自SingleThreadEventExecutor并且实现了EventLoop接口。

先来看下SingleThreadEventLoop的实现:

public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop

SingleThreadEventLoop使用单一线程来执行提交的任务。它和SingleThreadEventExecutor相比有什么变化呢?

首先 提供了一个tailTasks用来存储pending的tasks:

private final Queue<Runnable> tailTasks;

这个tailTasks会被用在任务个数的判断和操作上:

    final boolean removeAfterEventLoopIterationTask(Runnable task) {
return tailTasks.remove(ObjectUtil.checkNotNull(task, "task"));
} protected boolean hasTasks() {
return super.hasTasks() || !tailTasks.isEmpty();
} public int pendingTasks() {
return super.pendingTasks() + tailTasks.size();
}

SingleThreadEventLoop中对register方法的实现最终调用的是注册的channel中unsafe的register方法:

channel.unsafe().register(this, promise);

再来看一下DefaultEventLoop,DefaultEventLoop继承自SingleThreadEventLoop:

public class DefaultEventLoop extends SingleThreadEventLoop

除了构造函数之外,DefaultEventLoop实现了一个run方法,用来具体任务的执行逻辑:

    protected void run() {
for (;;) {
Runnable task = takeTask();
if (task != null) {
task.run();
updateLastExecutionTime();
} if (confirmShutdown()) {
break;
}
}
}

如果对比可以发现,DefaultEventLoop和DefaultEventExecutor中run方法的实现是一样的。

总结

本文介绍了netty中EventLoop和EventLoopGroup的默认实现:DefaultEventLoop和DefaultEventLoopGroup,但是不知道小伙伴们有没有发现,即使在最简单的netty应用中也很少看到这两个默认的EventLoop。最常用的反而是NioEventLoopGroup和NioEventLoop,这是因为DefaultEventLoop和DefaultEventLoopGroup只是使用了多线程技术,一个线程代表一个EventLoop,在EventLoop过多的情况下可能会造成线程和性能的浪费,所以在NioEventLoopGroup和NioEventLoop使用了NIO技术,通过使用channel、selector等NIO技术提升了EventLoop的效率。关于NioEventLoopGroup和NioEventLoop的详细介绍,我们会在后一章中详细讲解,敬请期待。

本文已收录于 http://www.flydean.com/05-1-netty-eventloop-eventloopgroup/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

netty系列之:EventLoop,EventLoopGroup和netty的默认实现的更多相关文章

  1. netty系列之:Bootstrap,ServerBootstrap和netty中的实现

    目录 简介 Bootstrap和ServerBootstrap的联系 AbstractBootstrap Bootstrap和ServerBootstrap 总结 简介 虽然netty很强大,但是使用 ...

  2. netty系列之:EventExecutor,EventExecutorGroup和netty中的实现

    目录 简介 EventExecutorGroup EventExecutor EventExecutorGroup在netty中的基本实现 EventExecutor在netty中的基本实现 总结 简 ...

  3. netty系列之:channel,ServerChannel和netty中的实现

    目录 简介 channel和ServerChannel netty中channel的实现 AbstractChannel和AbstractServerChannel LocalChannel和Loca ...

  4. Netty系列之Netty线程模型

    Reference: http://www.infoq.com/cn/articles/netty-threading-model 1. 背景 1.1. Java线程模型的演进 1.1.1. 单线程 ...

  5. netty系列之:netty初探

    目录 简介 netty介绍 netty的第一个服务器 netty的第一个客户端 运行服务器和客户端 总结 简介 我们常用浏览器来访问web页面得到相关的信息,通常来说使用的都是HTTP或者HTTPS协 ...

  6. netty系列之:中国加油

    目录 简介 场景规划 启动Server 启动客户端 消息处理 消息处理中的陷阱 总结 简介 之前的系列文章中我们学到了netty的基本结构和工作原理,各位小伙伴一定按捺不住心中的喜悦,想要开始手写代码 ...

  7. Netty 系列一(核心组件和实例).

    一.概念 早期的 Java API 只支持由本地系统套接字库提供所谓的阻塞函数来支持网络编程.由于是阻塞 I/O ,要管理多个并发客户端,需要为每个新的客户端Socket 创建一个 Thread .这 ...

  8. Netty 系列(三)Netty 入门

    Netty 系列(三)Netty 入门 Netty 是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠性的网络服务器和客户端程序.更多请参考:Netty Github 和 Netty中文 ...

  9. 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?

    [读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ? 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...

随机推荐

  1. CaCl2 项目介绍。

    一 是什么? 中国自然语言处理(NLP)研究项目. 二 主要功能? 从互联网获取的大量文本数据,结合自研力量进行分析.将数据重新格式化为大量条目,目录,并根据金融行业分类标准对这些条目进行了分类. 三 ...

  2. 「JOISC 2016 Day 1」棋盘游戏

    「JOISC 2016 Day 1」棋盘游戏 先判无解:第1,3行有连续的空格或四个角有空格. 然后可以发现有解的情况第1,3行可以在任意时间摆放. 对于某一列,若第2行放有棋子,那么显然可以把棋盘分 ...

  3. git 初始化本地项目并推送到远程

    有一个新项目,开发了一些代码之后想推送到远程,具体的操作方式和命令如下: (使用 git bash) 1.切到项目目录中,例如 E:\git\smart-open 2.初始化git仓库并在本地提交 / ...

  4. JAVA_HOME环境的配置

    JAVA_HOME环境的配置 有时候可能需要更换Jdk的目录,但是经常修改path的值可能会不小心修改其他的路径,解决方法: 1.  创建一个JAVA_HOME的变量. 2.  JAVA_HOME的值 ...

  5. 为什么要配置path环境变量

    因为在jdk下bin文件夹中有很多我们在开发中要使用的工具,如java.exe,javac.exe,jar.ex等,那么我们在使用时,想要在电脑的任意位置下使用这些java开发工具,那么我们就需有把这 ...

  6. Idea 如何不通过模板创建支持Maven的JavaWeb项目

    手动与模板创建的区别,请自行体会. 1. 点击创建项目 2. 不勾选骨架 3.填写项目名称以及该Maven项目坐标(groupid.artifactid.version). 在仓库中,以坐标确定项目. ...

  7. uniapp 使用iconfont图标

    步骤一 新建项目 步骤二 导入需要的图标,然后下载图标代码 步骤三  打开下载的压缩文件中的iconfont.css 步骤四 复制粘贴到项目中 步骤四在项目中使用 use in page

  8. PHP中英文混合字符串处理

    转载请注明来源:https://www.cnblogs.com/hookjc/ function cut_str($string, $sublen, $start = 0, $code = 'utf- ...

  9. Eclipse 堆栈和内存大小设置(转载)

    1,  设置Eclipse内存使用情况 修改eclipse根目录下的eclipse.ini文件 -vmargs  //虚拟机设置 -Xms40m -Xmx256m -XX:PermSize=128M ...

  10. Solution Set -「LOCAL」冲刺省选 Round XXIII

    \(\mathscr{Summary}\)   有一说一,虽然我炸了,但这场锻炼心态的效果真的好.部分分聊胜于无,区分度一题制胜,可谓针对性强的好题.   A 题,相对性签到题.这个建图确实巧妙,多见 ...