Netty中NioEventLoopGroup介绍

news2024/11/28 14:39:05

一、Netty基本介绍 

        Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。Netty 在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。

        Netty 是一个基于NIO的客户、服务器端的编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。

        本文主要介绍Netty中的核心类之一的:NioEventLoopGroup类。

二、NioEventLoopGroup继承体系

        从上往下看,关注第一个重点类,EventExecutorGroup类,这个类继承迭代器和支持延时启动线程池接口。所以这个类具有线程池和迭代器的一些行为,EventExecutorGroup声明了事件执行线程相关的操作,并支持迭代。在继承上述两个接口的的情况下,该类还扩展了其它接口:

public interface EventExecutorGroup extends ScheduledExecutorService, Iterable<EventExecutor> {

	/**
	 * 事件执行组是否已关闭
	 */
    boolean isShuttingDown();

	/**
	 * 优雅安全关闭事件执行组
	 */
    Future<?> shutdownGracefully();

	/**
	 * 支持延时优雅安全关闭事件执行组
	 */
    Future<?> shutdownGracefully(long var1, long var3, TimeUnit var5);
	
	/**
	 * 终止任务
	 */
    Future<?> terminationFuture();

	/**
	 * 获取下一个事件任务
	 */
    EventExecutor next();

}

         EventExecutorGroup主要操作的对象是EventExecutor,EventExecutor主要是对线程相关操作的声明,它的具体实现也主要是对线程相关操作的封装。我们看下EventExecutor接口:

public interface EventExecutor extends EventExecutorGroup {
    EventExecutor next();

    EventExecutorGroup parent();

    boolean inEventLoop();

    boolean inEventLoop(Thread var1);

    <V> Promise<V> newPromise();

    <V> ProgressivePromise<V> newProgressivePromise();

    <V> Future<V> newSucceededFuture(V var1);

    <V> Future<V> newFailedFuture(Throwable var1);
}

        上图EventExecutorGroup左边主要是对该类的部分实现和扩展,先右边往下看EventLoopGroup接口

public interface EventLoopGroup extends EventExecutorGroup {
    EventLoop next();

    ChannelFuture register(Channel var1);

    ChannelFuture register(ChannelPromise var1);

    /** @deprecated */
    @Deprecated
    ChannelFuture register(Channel var1, ChannelPromise var2);
}

        Netty通过事件循环机制(EventLoop)处理IO事件和异步任务。简单来说,就是通过一个死循环,不断处理当前已发生的IO事件和待处理的异步任务。这种事件循环机制也是一种常用的IO事件处理机制,包括Redis,Mysql都使用了类似的机制。EventLoopGroup负责调度EventLoop。该类也声明了EventLoopGroup需要实现的所有方法。

        EventLoopGroup扩展了将channel注册方法及迭代获取EventLoop方法,这里声明的register方法主要是将channel和EventLoop做一个绑定。

         EventLoopGroup有很多实现类,我们这里主要关注NioEventLoopGroup类

三、NioEventLoopGroup实现

        了解完上面的核心接口,我们关注一下具体的实现。先看下EventExecutorGroup的实现,参照上面继承体系,EventExecutorGroup左边一直往下看。

1.AbstractEventExecutorGroup

        AbstractEventExecutorGroup类对EventLoopGroup做了简单实现,主要是调用next()方法实现,并未做具体的实现,接着往下看。

2.MultithreadEventExecutorGroup

        我们先看看MultithreadEventExecutorGroup的成员变量

// 线程组数组
private final EventExecutor[] children;
// 线程集合
private final Set<EventExecutor> readonlyChildren;
// 终止的线程数
private final AtomicInteger terminatedChildren = new AtomicInteger();
// 线程终止通知
private final Promise<?> terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
// 线程选择器
private final EventExecutorChooserFactory.EventExecutorChooser chooser;

        我们看看Promise接口

/**
 * Special {@link Future} which is writable.
 */
public interface Promise<V> extends Future<V> {

    /**
     * Marks this future as a success and notifies all
     * listeners.
     *
     * If it is success or failed already it will throw an {@link IllegalStateException}.
     */
    Promise<V> setSuccess(V result);

    /**
     * Marks this future as a success and notifies all
     * listeners.
     *
     * @return {@code true} if and only if successfully marked this future as
     *         a success. Otherwise {@code false} because this future is
     *         already marked as either a success or a failure.
     */
    boolean trySuccess(V result);

    /**
     * Marks this future as a failure and notifies all
     * listeners.
     *
     * If it is success or failed already it will throw an {@link IllegalStateException}.
     */
    Promise<V> setFailure(Throwable cause);

    /**
     * Marks this future as a failure and notifies all
     * listeners.
     *
     * @return {@code true} if and only if successfully marked this future as
     *         a failure. Otherwise {@code false} because this future is
     *         already marked as either a success or a failure.
     */
    boolean tryFailure(Throwable cause);

    /**
     * Make this future impossible to cancel.
     *
     * @return {@code true} if and only if successfully marked this future as uncancellable or it is already done
     *         without being cancelled.  {@code false} if this future has been cancelled already.
     */
    boolean setUncancellable();

    @Override
    Promise<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);

    @Override
    Promise<V> addListeners(GenericFutureListener<? extends Future<? super V>>... listeners);

    @Override
    Promise<V> removeListener(GenericFutureListener<? extends Future<? super V>> listener);

    @Override
    Promise<V> removeListeners(GenericFutureListener<? extends Future<? super V>>... listeners);

    @Override
    Promise<V> await() throws InterruptedException;

    @Override
    Promise<V> awaitUninterruptibly();

    @Override
    Promise<V> sync() throws InterruptedException;

    @Override
    Promise<V> syncUninterruptibly();
}

        Promise类主要是绑定监听器,并在任务执行成功或失败的时候通知到绑定的监听器上。

        接着看下MultithreadEventExecutorGroup的构造方法

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
                                            EventExecutorChooserFactory chooserFactory, Object... args) {
	if (nThreads <= 0) {
		throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
	}

	if (executor == null) {
		executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
	}

	// 初始化线程组
	children = new EventExecutor[nThreads];

	for (int i = 0; i < nThreads; i ++) {
		boolean success = false;
		try {
			// 将线程和传入的executor做一个绑定
			// 注意:这里线程组每个元素都绑定了同一个executor
            // newChild是一个抽象方法,依赖子类实现
			children[i] = newChild(executor, args);
			success = true;
		} catch (Exception e) {
			// TODO: Think about if this is a good exception type
			throw new IllegalStateException("failed to create a child event loop", e);
		} finally {
			// 失败执行策略
			if (!success) {
				for (int j = 0; j < i; j ++) {
					children[j].shutdownGracefully();
				}

				for (int j = 0; j < i; j ++) {
					EventExecutor e = children[j];
					try {
						while (!e.isTerminated()) {
							e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
						}
					} catch (InterruptedException interrupted) {
						// Let the caller handle the interruption.
						Thread.currentThread().interrupt();
						break;
					}
				}
			}
		}
	}

	// 初始化一个EventExecutor选择工厂,轮询获取EventExecutor,chooserFactory的默认实现是DefaultEventExecutorChooserFactory
	// next()方法依赖chooser实现
	chooser = chooserFactory.newChooser(children);

	// 声明线程终止的监听器
	final FutureListener<Object> terminationListener = new FutureListener<Object>() {
		@Override
		public void operationComplete(Future<Object> future) throws Exception {
			if (terminatedChildren.incrementAndGet() == children.length) {
				terminationFuture.setSuccess(null);
			}
		}
	};

	// 将监听器绑定到线程组的每个线程中
	for (EventExecutor e: children) {
		e.terminationFuture().addListener(terminationListener);
	}

	// 初始化线程集合(只读)
	Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
	Collections.addAll(childrenSet, children);
	readonlyChildren = Collections.unmodifiableSet(childrenSet);
}

        newChild(executor, args)是一个抽象方法,需要依赖子类实现

3.MultithreadEventLoopGroup

        MultithreadEventLoopGroup继承了MultithreadEventExecutorGroup类做了简单实现,并覆盖了MultithreadEventExecutorGroup的newChild方法,将返回值覆盖为EventLoop

// MultithreadEventExecutorGroup类
protected abstract EventExecutor newChild(Executor executor, Object... args) throws Exception;

// MultithreadEventLoopGroup类
@Override
protected abstract EventLoop newChild(Executor executor, Object... args) throws Exception;

4.NioEventLoopGroup

        NioEventLoopGroup主要实现类一下的几个方法

/**
 * Sets the percentage of the desired amount of time spent for I/O in the child event loops.  The default value is
 * {@code 50}, which means the event loop will try to spend the same amount of time for I/O as for non-I/O tasks.
 * 设置IO百分比,默认50%
 */
public void setIoRatio(int ioRatio) {
	for (EventExecutor e: this) {
		((NioEventLoop) e).setIoRatio(ioRatio);
	}
}

/**
 * Replaces the current {@link Selector}s of the child event loops with newly created {@link Selector}s to work
 * around the  infamous epoll 100% CPU bug.
 * 覆盖事件循环选择器
 */
public void rebuildSelectors() {
	for (EventExecutor e: this) {
		((NioEventLoop) e).rebuildSelector();
	}
}

// 创建EventLoop对象,并绑定executor
@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
	return new NioEventLoop(this, executor, (SelectorProvider) args[0],
		((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}

        NioEventLoopGroup实现了MultithreadEventExecutorGroup的newChild方法,创建了一个NioEventLoop对象,本文主要是介绍NioEventLoopGroup内容,NioEventLoop在这里不展开讲,在后面会在分析NioEventLoop相关的内容。

        至此,NioEventLoopGroup的内容就介绍完毕了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/524343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cpuinfo库: 使用Python生成C++接口

文章目录 1. 目的2. 设计3. 生成器: Python 代码4. 结果: C++ 代码1. 目的 背景: cpuinfo 库提供了 CPU 信息的查询, 涵盖了 x86 和 arm 等常见的指令集架构, 可以提供自行实现的 CPU 基础功能函数的正确性验证。自行实现 CPU 基础功能则是为了简化功能、同时提供原汁原味…

详细介绍如何将博客图片从github/gitee批量转移到阿里云图床

背景介绍 我为什么想把博客文章中存储在github种的图片转移到阿里云呢&#xff1f; 存储在github中的图片有时会不稳定&#xff0c;破坏写文章过程中的思路和心流体验。写着写着就发现图片上传又出现问题了&#xff0c;很影响心情&#xff0c;阿里云是付费图床&#xff0c;在国…

【更新中】苹果自家的as汇编器的特色风格(与wasm的不同)

as汇编器是苹果的汇编器&#xff0c;Xcode 生成的代码也是as风格的&#xff0c;而as风格与大部分人在大学里所学的微软的masm风格大相径庭&#xff0c;所以本文会列出二者的不同。不过由于细节太多&#xff0c;没法一次性写出所有的不同&#xff0c;所以会持续更新。 你可能会…

linux常用系统工作命令

前言&#xff1a; 最近又重新抓起linux开始学习起来了&#xff0c;以前干过一段时间的菜鸟运维&#xff0c;对linux操作系统有点浅显的认识&#xff0c;中间又因为工作关系渐渐的又接触不到了&#xff0c;最近的博文算是回忆也当作笔记用&#xff0c;重新开始学习linux系统。 …

MYSQL主从复制和读写分离.1

1、什么是读写分离&#xff1f; 读写分离&#xff0c;基本的原理是让主数据库处理事务性增、删、改操作&#xff08;insert、update、delete&#xff09;&#xff0c;而从数据库处理select查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。 2、为什…

Mysql日志管理与备份恢复

目录 一、Mysql日志管理1、日志的分类1.1 错误日志1.2 通用查询日志1.3 二进制日志1.4 慢查询日志1.5 配置日志文件 2、日志的查询 二、Mysql备份与分类1、数据备份的重要性2、造成数据丢失的原因3、数据库备份的分类3.1 从物理与逻辑的角度划分3.2 从数据库的备份策略角度划分…

【配电网重构】基于SOE算法的多时段随机配电网重构方法【IEEE33节点、IEEE84节点】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

go语言channel(管道)和 select的结合使用

给个小建议&#xff1a;如果是初学者&#xff0c;建议把基础知识朗读一遍&#xff0c;有个大概印象&#xff0c;后面思考多了&#xff0c;就会“由量变达到质变”&#xff0c;从而有所顿悟。 目录 一、基础知识二、例子11、管道ch的缓冲区为10&#xff0c;select中有case读取管…

基于stm32物联网开发板(2)--LCD屏幕

基于stm32物联网开发板(2)–LCD屏幕 LCD应用展示&#xff1a; LCD屏幕应用 1.概述 屏幕尺寸为1.3寸&#xff0c;分辨率240*240&#xff0c;颜色格式RGB565&#xff0c;驱动IC&#xff1a;ST7789VW&#xff1b;超大可视角度:大于160(显示屏中可视角度最大的一种屏幕)&#xff1…

《深入理解Java虚拟机》JVM是怎么实现方法的动态调用的?方法句柄

《深入理解Java虚拟机》JVM是怎么实现方法的动态调用的&#xff1f;方法句柄 1.方法句柄出现的原因 某个国家举办了跑步比赛&#xff0c;有亚洲&#xff0c;欧洲还是非洲人参赛,但是有机器人也参赛了。机器人不属于人类阵营&#xff0c;怎么能让机器人也参加进来呢&#xff1…

Java递归生成树

1.建菜单表 CREATE TABLE t_menu ( id int(11) NOT NULL AUTO_INCREMENT, pid int(11) NOT NULL, name varchar(255) DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT11 DEFAULT CHARSETutf8mb4; 2.造一些数据 注意&#xff1a;根节点的pid0&#xff0c…

利用Rsoft开展弯曲光纤仿真分析

Rsoft是一款优秀的光学仿真软件&#xff0c;里面集成了多个模块&#xff0c;其中BPM模块利用光束传播法&#xff08;Beam Propagation Method&#xff09;&#xff0c;能够进行多种类型光器件的仿真&#xff0c;比如分束器、光纤等。这次&#xff0c;利用该模块展示如何开展光纤…

SpringSecurity简单的练手项目(SpringBoot+SpringSecurity+JWT)

文章目录 一、项目介绍二、SpringSecurity简介SpringSecurity中的几个重要组件&#xff1a;1.SecurityContextHolder&#xff08;class&#xff09;2.SecurityContext&#xff08;Interface&#xff09;3.Authentication&#xff08;Interface&#xff09;4.AuthenticationMana…

Eclipse的介绍与安装

Eclipse简介 Eclipse 是一个开放源代码的&#xff0c;基于 Java 的可扩展开发平台。Eclipse官方版是一个集成开发环境(IDE)&#xff0c;可以通过安装不同的插件实现对其它计算机语言编辑开发&#xff0c;如C、Php、Python等等。 Eclipse的下载 下载时需要访问网址 http://…

Android系统原理性问题分析 - RefBase、sp、wp 分析

声明 在Android系统中经常会遇到一些系统原理性的问题&#xff0c;在此专栏中集中来讨论下。接触Android系统&#xff0c;遇到很多sp、wp相关问题&#xff0c;此篇分析Android系统内的智能指针问题。此篇参考一些博客和书籍&#xff0c;代码基于Android 9.0.0&#xff0c;不方…

3D点云的基本操作(基于PCL编程)

知识储备 右手系 右手&#xff0c;拇指&#xff0c;食指&#xff0c;中指&#xff0c;分别是x,y,z的正方向。左手系则同理。 旋转矩阵 本质&#xff1a;两个坐标系之间的旋转关系。 用途&#xff1a;旋转点云。 原理&#xff1a;设传感器的坐标系为O1X1Y1Z1&#xff0c;设…

mysql 分组语句测试

建表 建表语句&#xff1a; CREATE TABLE student( id int not null, name char(12), sex char(1) ); 预置数据 insert into student values(1, wh, 1); insert into student values(2, wh1, 0); insert into student values(3, zyx, 0); commit; 增加字段 alt…

设计模式的分类、意图和适用性

文章目录 引言分类创建型设计模式Factory Method&#xff08;工厂方法&#xff09;Abstract Factory&#xff08;抽象工厂&#xff09;Builder&#xff08;生成器&#xff09;Prototype&#xff08;原型&#xff09;Singleton&#xff08;单例&#xff09; 结构型设计模式Adapt…

【二】设计模式~~~创建型模式~~~工厂方法模式(Java)

【学习难度&#xff1a;★★☆☆☆&#xff0c;使用频率&#xff1a;★★★★★】 2.1. 模式动机 现在对该系统进行修改&#xff0c;不再设计一个按钮工厂类来统一负责所有产品的创建&#xff0c;而是将具体按钮的创建过程交给专门的工厂子类去完成&#xff0c;我们先定义一个…

【周末闲谈】超越ChatGPT?科大讯飞星火认知大模型

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 ✨第一周 二进制VS三进制 ✨第二周 文心一言&#xff0c;模仿还是超越&#xff1f; ✨第二周 畅想AR 文章目录 前言星火名字的由来科大讯飞星火落地应用演示赶超ChatGPT的底气在哪里?“硬…