Netty源码分析系列1——NIOEventLoopGroup的创建


netty4服务端启动源码分析-线程的创建

转载:http://xw-z1985.iteye.com/blog/1924124

 

本文分析Netty中boss和worker的线程的创建过程:

以下代码是服务端的启动代码,线程的创建就发生在其中。

EventLoopGroup bossGroup = new NioEventLoopGroup();

 

NioEventLoopGroup的类关系图如下:


Netty源码分析系列1——NIOEventLoopGroup的创建_第1张图片
 构造方法执行过程如下:

 

Java代码  
  1. // NioEventLoopGroup  
  2. public NioEventLoopGroup() {  
  3.         this(0);  
  4.     }  
  5.   
  6. public NioEventLoopGroup(int nThreads) {  
  7.         this(nThreads, null);  
  8.     }  
  9.   
  10. public NioEventLoopGroup(int nThreads, ThreadFactory threadFactory) {  
  11.         this(nThreads, threadFactory, SelectorProvider.provider());  
  12.     }  
  13.   
  14. public NioEventLoopGroup(  
  15.             int nThreads, ThreadFactory threadFactory, final SelectorProvider selectorProvider) {  
  16.         super(nThreads, threadFactory, selectorProvider);  
  17.     }  

 看下父类MultithreadEventLoopGroup的构造方法

Java代码  
  1. // MultithreadEventLoopGroup  
  2. protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {  
  3.         super(nThreads == 0? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);  
  4.     }  

 注:如果没有指定创建的线程数量,则默认创建的线程个数为DEFAULT_EVENT_LOOP_THREADS,该数值为:处理器数量x2

 

再来看MultithreadEventLoopGroup的父类MultithreadEventExecutorGroup的构造方法

 

Java代码  
  1. /** 
  2.     * Create a new instance. 
  3.     * 
  4.     * @param nThreads          the number of threads that will be used by this instance. 
  5.     * @param threadFactory     the ThreadFactory to use, or {@code null} if the default should be used. 
  6.     * @param args              arguments which will passed to each {@link #newChild(ThreadFactory, Object...)} call 
  7.     */  
  8.    protected MultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args) {  
  9.        if (nThreads <= 0) {  
  10.            throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));  
  11.        }  
  12.   
  13.        if (threadFactory == null) {  
  14.            threadFactory = newDefaultThreadFactory();  
  15.        }  
  16.   
  17.        children = new SingleThreadEventExecutor[nThreads];  
  18.        for (int i = 0; i < nThreads; i ++) {  
  19.            boolean success = false;  
  20.            try {  
  21.                children[i] = newChild(threadFactory, args);  
  22.                success = true;  
  23.            } catch (Exception e) {  
  24.                // TODO: Think about if this is a good exception type  
  25.                throw new IllegalStateException("failed to create a child event loop", e);  
  26.            } finally {  
  27.                if (!success) {  
  28.                    for (int j = 0; j < i; j ++) {  
  29.                        children[j].shutdownGracefully();  
  30.                    }  
  31.   
  32.                    for (int j = 0; j < i; j ++) {  
  33.                        EventExecutor e = children[j];  
  34.                        try {  
  35.                            while (!e.isTerminated()) {  
  36.                                e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);  
  37.                            }  
  38.                        } catch (InterruptedException interrupted) {  
  39.                            Thread.currentThread().interrupt();  
  40.                            break;  
  41.                        }  
  42.                    }  
  43.                }  
  44.            }  
  45.        }  
  46.   
  47.        final FutureListener terminationListener = new FutureListener() {  
  48.            @Override  
  49.            public void operationComplete(Future future) throws Exception {  
  50.                if (terminatedChildren.incrementAndGet() == children.length) {  
  51.                    terminationFuture.setSuccess(null);  
  52.                }  
  53.            }  
  54.        };  
  55.   
  56.        for (EventExecutor e: children) {  
  57.            e.terminationFuture().addListener(terminationListener);  
  58.        }  
  59.    }  
  60.  变量children就是用来存放创建的线程的数组,里面每一个元素都通过children[i] = newChild(threadFactory, args)创建。而newChild方法则由子类NioEventLoopGroup实现

     

    Java代码  
    1. // NioEventLoopGroup  
    2.   protected EventExecutor newChild(  
    3.             ThreadFactory threadFactory, Object... args) throws Exception {  
    4.         return new NioEventLoop(this, threadFactory, (SelectorProvider) args[0]);  
    5.     }  

     每个元素的真实类型为NioEventLoop,而NioEventLoop的类关系图如下

     


    Netty源码分析系列1——NIOEventLoopGroup的创建_第2张图片
     (注:其实有点变态的,譬如EventLoop继承EventLoopGroup,不知道是啥原因,仅仅是因为EventLoop里有个方法parent(),返回EventLoopGroup这个功能吗?后续待确认)

     

    接着看NioEventLoop的构造函数:

     

    Java代码  
    1. // NioEventLoop  
    2.  NioEven NioEventLoop tLoop(NioEventLoopGroup parent, ThreadFactory threadFactory, SelectorProvider selectorProvider) {  
    3.         super(parent, threadFactory, false);  
    4.         if (selectorProvider == null) {  
    5.             throw new NullPointerException("selectorProvider");  
    6.         }  
    7.         provider = selectorProvider;  
    8.         selector = openSelector();  
    9.     }  

     首先分析一下selector = openSelector()

     

     

    Java代码  
    1. // NioEventLoop  
    2.  private Selector openSelector() {  
    3.         final Selector selector;  
    4.         try {  
    5.             selector = provider.openSelector();  
    6.         } catch (IOException e) {  
    7.             throw new ChannelException("failed to open a new selector", e);  
    8.         }  
    9.   
    10.         if (DISABLE_KEYSET_OPTIMIZATION) {  
    11.             return selector;  
    12.         }  
    13.   
    14.         try {  
    15.             SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();  
    16.   
    17.             Class selectorImplClass =  
    18.                     Class.forName("sun.nio.ch.SelectorImpl", false, ClassLoader.getSystemClassLoader());  
    19.             selectorImplClass.isAssignableFrom(selector.getClass());  
    20.             Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");  
    21.             Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");  
    22.   
    23.             selectedKeysField.setAccessible(true);  
    24.             publicSelectedKeysField.setAccessible(true);  
    25.   
    26.             selectedKeysField.set(selector, selectedKeySet);  
    27.             publicSelectedKeysField.set(selector, selectedKeySet);  
    28.   
    29.             selectedKeys = selectedKeySet;  
    30.             logger.trace("Instrumented an optimized java.util.Set into: {}", selector);  
    31.         } catch (Throwable t) {  
    32.             selectedKeys = null;  
    33.             logger.trace("Failed to instrument an optimized java.util.Set into: {}", selector, t);  
    34.         }  
    35.   
    36.         return selector;  
    37.     }  

           这里对sun.nio.ch.SelectorImpl中的selectedKeys和publicSelectedKeys做了优化,NioEventLoop中的变量selectedKeys的类型是SelectedSelectionKeySet,有哪些优化呢?(内部用两个数组存储?初始分配数组大小置为1024避免频繁扩容?当大小超过1024时,对数组进行双倍扩容?)。

           利用反射,当注册到selector中的selectionKey已准备就绪时,selectedKeys中的元素就不会为空,后面会根据selectedKeys进行分发。

     

    最后分析super(parent, threadFactory, false),即父类SingleThreadEventExecutor的构造函数

    Java代码  
    1. /** 
    2.     * Create a new instance 
    3.     * 
    4.     * @param parent            the {@link EventExecutorGroup} which is the parent of this instance and belongs to it 
    5.     * @param threadFactory     the {@link ThreadFactory} which will be used for the used {@link Thread} 
    6.     * @param addTaskWakesUp    {@code true} if and only if invocation of {@link #addTask(Runnable)} will wake up the 
    7.     *                          executor thread 
    8.     */  
    9.    protected SingleThreadEventExecutor(  
    10.            EventExecutorGroup parent, ThreadFactory threadFactory, boolean addTaskWakesUp) {  
    11.   
    12.        if (threadFactory == null) {  
    13.            throw new NullPointerException("threadFactory");  
    14.        }  
    15.   
    16.        this.parent = parent;  
    17.        this.addTaskWakesUp = addTaskWakesUp;  
    18.   
    19.        thread = threadFactory.newThread(new Runnable() {  
    20.            @Override  
    21.            public void run() {  
    22.                boolean success = false;  
    23.                updateLastExecutionTime();  
    24.                try {  
    25.                    SingleThreadEventExecutor.this.run();  
    26.                    success = true;  
    27.                } catch (Throwable t) {  
    28.                    logger.warn("Unexpected exception from an event executor: ", t);  
    29.                } finally {  
    30.                    if (state < ST_SHUTTING_DOWN) {  
    31.                        state = ST_SHUTTING_DOWN;  
    32.                    }  
    33.   
    34.                    // Check if confirmShutdown() was called at the end of the loop.  
    35.                    if (success && gracefulShutdownStartTime == 0) {  
    36.                        logger.error(  
    37.                                "Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +  
    38.                                SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must be called " +  
    39.                                "before run() implementation terminates.");  
    40.                    }  
    41.   
    42.                    try {  
    43.                        // Run all remaining tasks and shutdown hooks.  
    44.                        for (;;) {  
    45.                            if (confirmShutdown()) {  
    46.                                break;  
    47.                            }  
    48.                        }  
    49.                    } finally {  
    50.                        try {  
    51.                            cleanup();  
    52.                        } finally {  
    53.                            synchronized (stateLock) {  
    54.                                state = ST_TERMINATED;  
    55.                            }  
    56.                            threadLock.release();  
    57.                            if (!taskQueue.isEmpty()) {  
    58.                                logger.warn(  
    59.                                        "An event executor terminated with " +  
    60.                                        "non-empty task queue (" + taskQueue.size() + ')');  
    61.                            }  
    62.   
    63.                            terminationFuture.setSuccess(null);  
    64.                        }  
    65.                    }  
    66.                }  
    67.            }  
    68.        });  
    69.   
    70.        taskQueue = newTaskQueue();  
    71.    }  
    72.   
    73.    /** 
    74.     * Create a new {@link Queue} which will holds the tasks to execute. This default implementation will return a 
    75.     * {@link LinkedBlockingQueue} but if your sub-class of {@link SingleThreadEventExecutor} will not do any blocking 
    76.     * calls on the this {@link Queue} it may make sense to {@code @Override} this and return some more performant 
    77.     * implementation that does not support blocking operations at all. 
    78.     */  
    79.    protected Queue newTaskQueue() {  
    80.        return new LinkedBlockingQueue();  
    81.    }  

     boss线程就在此处创建:thread = threadFactory.newThread(new Runnable()

    同时也创建了线程的任务队列,是一个LinkedBlockingQueue结构。

    SingleThreadEventExecutor.this.run()由子类NioEventLoop实现,后面的文章再进行分析

     

    总结:

    EventLoopGroup bossGroup = new NioEventLoopGroup()发生了以下事情:

          1、 为NioEventLoopGroup创建数量为:处理器个数 x 2的,类型为NioEventLoop的实例。每个NioEventLoop实例 都持有一个线程,以及一个类型为LinkedBlockingQueue的任务队列

          2、线程的执行逻辑由NioEventLoop实现

          3、每个NioEventLoop实例都持有一个selector,并对selector进行优化。

    你可能感兴趣的:(Netty源码分析系列1——NIOEventLoopGroup的创建)