selector在没有结果的情况下,依然被唤醒,导致一直空轮询,cpu100%

直接定位到NioEventLoop

@Override

protected void run() {

for (;;) {

try {

switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {

case SelectStrategy.CONTINUE:

continue;

case SelectStrategy.SELECT:

select(wakenUp.getAndSet(false));

if (wakenUp.get()) {

selector.wakeup();

}

default:

// fallthrough

}

cancelledKeys = 0;

needsToSelectAgain = false;

final int ioRatio = this.ioRatio;

if (ioRatio == 100) {

try {

processSelectedKeys();

} finally {

// Ensure we always run tasks.

runAllTasks();

}

} else {

final long ioStartTime = System.nanoTime();

try {

processSelectedKeys();

} finally {

// Ensure we always run tasks.

final long ioTime = System.nanoTime() - ioStartTime;

runAllTasks(ioTime * (100 - ioRatio) / ioRatio);

}

}

} catch (Throwable t) {

handleLoopException(t);

}

try {

if (isShuttingDown()) {

closeAll();

if (confirmShutdown()) {

return;

}

}

} catch (Throwable t) {

handleLoopException(t);

}

}

}

第二个case,SelectStrategy.SELECT ,其值为-1。跟进调用的select方法。

private void select(boolean oldWakenUp) throws IOException {

Selector selector = this.selector;

try {

int selectCnt = 0;

long currentTimeNanos = System.nanoTime();

long selectDeadLineNanos = currentTimeNanos + delayNanos(currentTimeNanos);

for (;;) {

long timeoutMillis = (selectDeadLineNanos - currentTimeNanos + 500000L) / 1000000L;

if (timeoutMillis <= 0) {

if (selectCnt == 0) {

selector.selectNow();

selectCnt = 1;

}

break;

}

if (hasTasks() && wakenUp.compareAndSet(false, true)) {

selector.selectNow();

selectCnt = 1;

break;

}

int selectedKeys = selector.select(timeoutMillis);

selectCnt ++;

if (selectedKeys != 0 || oldWakenUp || wakenUp.get() || hasTasks() || hasScheduledTasks()) {

break;

}

if (Thread.interrupted()) {

if (logger.isDebugEnabled()) {

logger.debug("Selector.select() returned prematurely because " +

"Thread.currentThread().interrupt() was called. Use " +

"NioEventLoop.shutdownGracefully() to shutdown the NioEventLoop.");

}

selectCnt = 1;

break;

}

long time = System.nanoTime();

if (time - TimeUnit.MILLISECONDS.toNanos(timeoutMillis) >= currentTimeNanos) {

// timeoutMillis elapsed without anything selected.

selectCnt = 1;

} else if (SELECTOR_AUTO_REBUILD_THRESHOLD > 0 &&

selectCnt >= SELECTOR_AUTO_REBUILD_THRESHOLD) {

// The selector returned prematurely many times in a row.

// Rebuild the selector to work around the problem.

logger.warn(

"Selector.select() returned prematurely {} times in a row; rebuilding Selector {}.",

selectCnt, selector);

rebuildSelector();

selector = this.selector;

// Select again to populate selectedKeys.

selector.selectNow();

selectCnt = 1;

break;

}

currentTimeNanos = time;

}

if (selectCnt > MIN_PREMATURE_SELECTOR_RETURNS) {

if (logger.isDebugEnabled()) {

logger.debug("Selector.select() returned prematurely {} times in a row for Selector {}.",

selectCnt - 1, selector);

}

}

} catch (CancelledKeyException e) {

if (logger.isDebugEnabled()) {

logger.debug(CancelledKeyException.class.getSimpleName() + " raised by a Selector {} - JDK bug?",

selector, e);

}

// Harmless exception - log anyway

}

}

上述代码中在轮询之前,先定义当前时间currentTimeNanos。接着计算出一个执行最少需要的时间timeoutMillis。每次对selectCnt做++操作。

在后面的代码中通过

time - TimeUnit.MILLISECONDS.toNanos(timeoutMillis) >= currentTimeNanos

进行判断,如果到达执行到最少时间,则seletCnt重置为1。一旦到达SELECTOR_AUTO_REBUILD_THRESHOLD这个阀值,就需要重建selector来解决这个问题。这个阀值默认是512。

java为什么不解决空轮询,netty解决空轮询bug相关推荐

  1. Netty解决TCP的粘包和分包(二)

    2019独角兽企业重金招聘Python工程师标准>>> Netty解决TCP的粘包和分包(二) 使用LengthFieldBasedFrameDecoder解码器分包 先看一下这个类 ...

  2. Netty解决TCP粘包/拆包导致的半包读写问题

    一.TCP粘包/拆包问题说明 TCP是个"流"协议,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包拆分,所以在业务上认为,一 ...

  3. java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 解决方法 java.lang.ClassNotFoundException: com.

    java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 解决方法 java.lang.ClassNotFoundException: com.m ...

  4. java无阻塞执行脚本,JAVA调用Shell脚本-及阻塞的解决方法

    JAVA调用Shell脚本--及阻塞的解决办法 用java调用shell,使用 Process p=Runtime.getRuntime().exec(String[] cmd); Runtime.e ...

  5. Adobe flash cs5 的Java运行时环境初始化错误 完美解决方法

    Adobe flash cs5 的Java运行时环境初始化错误 完美解决方法 下载网络上的Adobe flash cs5 精简版(绿色版),Java运行时环境初始化时出现错误,你可能需要重装Flash ...

  6. java开发中遇到的问题及解决方法(持续更新)

    java开发中遇到的问题及解决方法(持续更新) 参考文章: (1)java开发中遇到的问题及解决方法(持续更新) (2)https://www.cnblogs.com/LiuYanYGZ/p/6112 ...

  7. Android DialogFragment 遇到 java.lang.IllegalStateException: Fragment already added: 的解决方法

    Android DialogFragment 遇到 java.lang.IllegalStateException: Fragment already added: 的解决方法 参考文章: (1)An ...

  8. java.net.UnknownHostException: unknown host:xxxx异常解决办法

    java.net.UnknownHostException: unknown host:xxxx异常解决办法 参考文章: (1)java.net.UnknownHostException: unkno ...

  9. Idea运行web项目时,提示java.lang.ClassNotFoundException: com.mysql.jdbc.Driver解决方法

    Idea运行web项目时,提示java.lang.ClassNotFoundException: com.mysql.jdbc.Driver解决方法 参考文章: (1)Idea运行web项目时,提示j ...

最新文章

  1. svn: Working copy locked
  2. Firebug Console 与命令行全集
  3. 360脱口秀:‘未来属于虚拟’开播啦!
  4. catia 快捷键 激活零件_CATIA基本操作技巧
  5. 轻松得到C# ADO.NET的各种数据库连接字符串
  6. [黑马程序员二]:C#面向对象基础
  7. 异常规范之阿里巴巴开发手册中的异常规范讲解
  8. 数据结构之希尔排序------java实现
  9. [Cordova]JS和Native交互实现关键代码(iOS)
  10. 启动NameNode和DataNode
  11. EVCache缓存在 Spring Boot中的实战
  12. 荷兰铁路在采纳敏捷和精益中的做法
  13. Linux中下载,压缩,解压等命令
  14. java 栈泛型_使用泛型实现栈结构
  15. 常见API漏洞解释以及应用层解决方案
  16. 汉字转拼音,多音字解决方案
  17. Altium Designer入门与进阶教程系列
  18. 【网络安全】黑客攻防与入侵检测(练习题)
  19. 《计算机网络自顶向下》Socket Lab2 UDP Pinger Lab
  20. php 中断请求,PHP 信号中断系统

热门文章

  1. 超炫酷的Markdown渲染阅读工具(附开源地址)
  2. 由粗模生细模 精灵4 RTK结合PhotoScan航线规划生成精细化模型
  3. 三位分节制顺口溜_小学数学学习中36类顺口溜,说给孩子听
  4. vysor无线连接投屏使用/wifi连接+Vysor_2.1.2Pro安装教程+谷歌vysor插件防止自动更新
  5. 恒源云(Gpushare)_如何查看显卡占用的情况?技巧大放送2
  6. 上计算机课如何摆脱桌面控制,(信息老师必读)防止学生摆脱电子教室控制的方法、信息课怎样防止学生不受控制...
  7. MySQL存储引擎与数据的关系_MySQL存储引擎与数据类型
  8. js replace正则替换 \n
  9. python 最小堆类型: heapq
  10. git命令行账号切换