1、 BUG出现的原因:
若Selector的轮询结果为空,也没有wakeup或新消息处理,则发生N多次空轮询,使得CPU使用率100%
2、Netty中的解决思路:
对Selector()方法中的阻塞定时 select(timeMIllinois)操作的 次数进行统计,每完成一次select操作进行一次计数,若在循环周期内 发生N次空轮询,如果N值大于BUG阈值(默认为512),就进行空轮询BUG处理。重建Selector,判断是否是其他线程发起的重建请求,若不是则将原SocketChannel从旧的Selector上去除注册,重新注册到新的 Selector上,并将原来的Selector关闭。
源码:已将部分代码省略,全部代码在io.netty.channel.nio.NioEventLoop类当中的select()方法中。
select方法分三个部分:
//第一部分:超时处理逻辑
//第二部分:定时阻塞select(timeMillins)
// 第三步: 解决空轮询 BUG
long time = System.nanoTime();
//此处的逻辑就是: 当前时间 - 循环开始时间 >= 定时select的时间timeoutMillis,说明已经执行过一次阻塞select()
if (time - TimeUnit.MILLISECONDS.toNanos(timeoutMillis) >= currentTimeNanos) {
selectCnt = 1; // 说明发生过一次阻塞式轮询
// 如果空轮询的次数大于空轮询次数阈值 SELECTOR_AUTO_REBUILD_THRESHOLD(512)
} else if (SELECTOR_AUTO_REBUILD_THRESHOLD > 0 && selectCnt >= SELECTOR_AUTO_REBUILD_THRESHOLD) {
/* setlctRebuildSelector():
* 1.首先创建一个新的Selecor
* 2.将旧的Selector上面的键及其一系列的信息放到新的selector上面。
/*
selector = this.selectRebuildSelector(selectCnt);
selectCnt = 1;
break;
}
currentTimeNanos = time;
转:https://blog.csdn.net/qq_41884976/article/details/91913820