Netty 源码阅读笔记(1) NioEventLoopGroup

本文深入解析了NioEventLoopGroup的构造方法及其内部类结构,详细介绍了如何通过不同的构造参数创建线程组,特别关注了线程数量的默认设定及bossEventLoopGroup的创建过程。

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

类结构图

在这里插入图片描述

1.1 构造方法

public NioEventLoopGroup() {
    this(0);
}

public NioEventLoopGroup(int nThreads) {
    this(nThreads, (Executor) null);
}

public NioEventLoopGroup(int nThreads, Executor executor) {
    this(nThreads, executor, SelectorProvider.provider());
}

public NioEventLoopGroup(
        int nThreads, Executor executor, final SelectorProvider selectorProvider) {
    this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
}

public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
                         final SelectStrategyFactory selectStrategyFactory) {
    super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}

类 MultithreadEventLoopGroup

protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
    super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}

private static final int DEFAULT_EVENT_LOOP_THREADS;

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

    if (logger.isDebugEnabled()) {
        logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
    }
}

可以看到如果调用无参构造,线程数会是 2*Ncpu,这适合 workerEventLoopGroup。
创建 bossEventLoopGroup 就需要加个参数 1。

类 MultithreadEventExecutorGroup

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
    this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}

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) {
    	//实例化每个EventLoop所需要的执行器Executor 见(2)
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
    }

	//NioEventLoop是EventExecutor的实现类 
    children = new EventExecutor[nThreads];

    for (int i = 0; i < nThreads; i ++) {
        boolean success = false;
        try {
        					//见1.1.1
            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;
                    }
                }
            }
        }
    }

    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);
}

1.1.1 newChild

类 MultithreadEventExecutorGroup

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

这是一个接口

类 NioEventLoopGroup

@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
				//见(3)
    return new NioEventLoop(this, executor, (SelectorProvider) args[0],
        ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
<think>好的,我需要帮助用户获取关于Netty的全面学习资料或教程。首先,我需要回顾用户提供的引用内容,看看有哪些现有的资源可以整合。 用户提供了五个引用,其中引用[1]和[2]提到了尚硅谷的Netty系列学习笔记,包括BIO、NIO、AIO的介绍以及代码示例。引用[3]详细描述了Netty客户端的初始化步骤和关键组件,引用[4]和[5]讨论了NIO的优势以及Reactor模型的优缺点。这些引用内容虽然分散,但可以作为构建学习路径的基础。 接下来,我需要按照用户的要求,将回答结构化,分步骤说明。用户需要全面的学习资料,所以应该涵盖基础概念、核心组件、实践资源和进阶内容。同时,必须确保所有数学公式和独立公式符合规定的格式,但在这个主题中可能数学内容较少,主要集中在代码示例和技术术语上。 需要检查是否每个引用都被恰当地引用,并在末尾添加标识。例如,在介绍BIO/NIO时引用[1][4],在讲解Netty组件时引用[2][3],在讨论线程模型时引用[5]。 然后,生成相关问题。用户示例中的相关问题涉及性能分析、优化方法和应用场景,我需要针对Netty提出类似的问题,比如学习路径、核心组件的作用、线程模型的选择等。 最后,确保回答符合中文要求,结构清晰,语言自然,避免使用Markdown格式,用口语化的表达,同时保持专业性。需要确认所有引用标记正确,没有遗漏,并且链接到对应的引用来源。</think>### Netty全面学习路径指南 #### 一、基础理论准备 1. **理解IO模型演进** - 需掌握$BIO$(阻塞IO)在连接数多时产生大量线程的问题[^1] - 理解$NIO$(非阻塞IO)的三大核心:通道(Channel)、缓冲区(Buffer)、选择器(Selector)[^4] - 对比$AIO$(异步IO)在Linux系统下支持不足的特点 2. **Reactor模式精要** - 单Reactor单线程模型适用于低并发场景 - 主从Reactor多线程模型通过$$线程池=主线程(事件分发) + 子线程(业务处理)$$结构实现高吞吐[^5] #### 二、Netty核心组件解析 1. **核心架构要素** - **Bootstrap**:客户端入口类,通过`group()`配置线程池[^3] - **NioSocketChannel**:客户端通道类型,需设置`SO_KEEPALIVE`等参数 - **ChannelPipeline**:通过`addLast()`添加编解码器、业务处理器 2. **关键注解应用** `@ChannelHandler.Sharable`注解实现处理器单例复用,需注意线程安全问题 #### 三、实践资源推荐 1. **学习仓库推荐** - [Github-netty-learn](https://github.com/example/netty-learn)(含NIO基础到集群聊天案例)[^2] - [Gitee-netty-learn](https://gitee.com/example/netty-learn)(国内镜像仓库)[^2] 2. **代码实践路线** ```java // 典型客户端初始化代码 EventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new SimpleClientHandler()); } }); ``` 此代码演示了线程池配置、通道类型指定、处理器链构建 #### 四、进阶学习方向 1. **性能优化专题** - 对象池技术减少GC压力 - 零拷贝技术应用(FileRegion类使用) 2. **源码研读重点** - EventLoop事件循环机制 - ByteBuf内存管理设计
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值