Netty源码分析 NioEventLoop的rebuildSelector方法解决Nio中select方法导致cpu100%的BUG

Posted 征服.刘华强

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty源码分析 NioEventLoop的rebuildSelector方法解决Nio中select方法导致cpu100%的BUG相关的知识,希望对你有一定的参考价值。

 


//重新创建Selector
public void rebuildSelector() 
    //判断是否是当前线程,如果是其它现成则加入队列,让单钱线程执行方法
    if (!inEventLoop()) 
        execute(new Runnable() 
            @Override
            public void run() 
                rebuildSelector0();
            
        );
        return;
    
    //内部方法
    rebuildSelector0();


private void rebuildSelector0() 
    //旧的选择器对象
    final Selector oldSelector = selector;

    //新的选择器对象
    final SelectorTuple newSelectorTuple;

    if (oldSelector == null) 
        return;
    

    try 
        //创建一个新的选择器
        newSelectorTuple = openSelector();
     catch (Exception e) 
        logger.warn("Failed to create a new Selector.", e);
        return;
    


    // Register all channels to the new Selector.
    int nChannels = 0;
    //循环所有旧选择器上的key
    for (SelectionKey key: oldSelector.keys()) 

        //拿到key关联的对象
        Object a = key.attachment();
        try 
            //如果key无效 或者 channel已经关联到新选择器则循环下一个key
            if (!key.isValid() || key.channel().keyFor(newSelectorTuple.unwrappedSelector) != null) 
                continue;
            

            //key之前绑定的事件类型
            int interestOps = key.interestOps();

            //把key取消
            key.cancel();

            //新的key,绑定到新的selector
            SelectionKey newKey = key.channel().register(newSelectorTuple.unwrappedSelector, interestOps, a);
            //如果之前key关联的对象时AbstractNioChannel,则更新key的引用为newKey
            if (a instanceof AbstractNioChannel) 
                // Update SelectionKey
                ((AbstractNioChannel) a).selectionKey = newKey;
            
            nChannels ++;
         catch (Exception e) 
            logger.warn("Failed to re-register a Channel to the new Selector.", e);
            if (a instanceof AbstractNioChannel) 
                AbstractNioChannel ch = (AbstractNioChannel) a;
                ch.unsafe().close(ch.unsafe().voidPromise());
             else 
                @SuppressWarnings("unchecked")
                NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
                invokeChannelUnregistered(task, key, e);
            
        
    

    //更新成员变量
    selector = newSelectorTuple.selector;
    unwrappedSelector = newSelectorTuple.unwrappedSelector;

    try 
        //关闭旧选择器
        // time to close the old selector as everything else is registered to the new one
        oldSelector.close();
     catch (Throwable t) 
        if (logger.isWarnEnabled()) 
            logger.warn("Failed to close the old Selector.", t);
        
    

    if (logger.isInfoEnabled()) 
        logger.info("Migrated " + nChannels + " channel(s) to the new Selector.");
    

 

以上是关于Netty源码分析 NioEventLoop的rebuildSelector方法解决Nio中select方法导致cpu100%的BUG的主要内容,如果未能解决你的问题,请参考以下文章

Netty源码分析之NioEventLoop执行流程

Netty4.XNetty源码分析之NioEventLoop

Netty源码分析 NioEventLoop的rebuildSelector方法解决Nio中select方法导致cpu100%的BUG

6. Netty源码分析之EventLoop与EventLoopGroup

Netty核心组件之NioEventLoop(一)

Netty源码_NioEventLoop详解