(本文尚未完工! 本文尚未完工! )

何为线程模型?

说到线程模型,可能是指操作系统如何实现用户级线程,比如many to many,many to one,one to one;也可能是指编程语言对多线程的支持方式,或者直接提供对操作系统线程API的访问,或者在其之上提供一层抽象以屏蔽平台间的差异,或者干脆不提供并发和线程,等等。

而这里讨论的线程模型,是另外一种情况,指的是应用程序或者框架对线程的使用情况:

  • 有哪些线程
  • 如何管理这些线程
  • 线程的生命周期(何时创建何时销毁)
  • 各线程的职责

为什么要了解线程模型?

借用Netty in Action中的一段话:

How and when threads are created obviously has a significant impact on the execution of application code, so developers need to understand the trade-offs associated with different models. This is true whether they choose the model themselves or acquire it implicitly via the adoption of a language or framework.

而我之所以想去了解Netty的线程模型正是因为黑体部分,因为我现在所参与的项目不仅仅是把Netty当做一个网络框架,更把它当做一个业务容器来使用,可以说Netty的线程模型就是我们业务应用的线程模型,90%的业务逻辑都是由Netty的IO线程来驱动的(这种方式是好是坏这里不做讨论)。

还有一段有点“墨菲定律”的意思:

As we pointed out at the start of the chapter, a threading model specifies how code is going to be executed. Because we must always guard against the possible side effects of concurrent execution, it’s important to understand the implications of the model being applied (there are single-thread models as well). Ignoring these matters and merely hoping for the best is tantamount to gambling—with the odds definitely against you.

分析Netty 4 的线程模型

下面通过调试以及阅读相关源码的方式,以一个实际的Netty应用为例,来分析Netty 4的线程模型。

示例所使用的Netty版本为4.1.37.Final。因为我目前所参与的项目的原因,示例代码没有选择使用nio,而是选择了Linux专用的epoll,两者在线程模型上应该是没区别的。

从一个最简单的Netty应用开始:

package com.wallenwang.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.socket.SocketChannel;

public final class Server {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new EpollEventLoopGroup(2);
        EventLoopGroup workerGroup = new EpollEventLoopGroup(4);
        ServerBootstrap b = new ServerBootstrap();

        b.group(bossGroup, workerGroup)
         .channel(EpollServerSocketChannel.class)
         .childHandler(new ChannelInitializer<SocketChannel>() {
             @Override
             public void initChannel(SocketChannel ch) throws Exception {
             }
         });

        // Start the server.
        ChannelFuture f = b.bind(9).sync();

        // Wait until the server socket is closed.
        f.channel().closeFuture().sync();

        // Shut down all event loops to terminate all threads.
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}
继续阅读