空的死循环为什么会让cpu100%

 while (1) {
  //空代码块
 }

      上面这个代码相信很多人都写过,这个代码的后果就是cpu会100%(具体数值要看cpu核数和操作系统对这个的表示方法,有的2核会显示50%,有的2核会显示100%),如果是单核那么你的电脑会相当卡了。解决这个问题的办法很简单

 while (1) {
     sleep(1);
 }

加上一个sleep(1),让她休眠一秒就好了。现在都是多任务操作系统了,电脑上不会只有这一个进程,cpu不是按时间片轮转来执行吗?就算是单核,cpu利用率也不应该是100%啊,为什么会这样呢?我们知道一个线程有三种状态:

 

假设现在加上这个  空的死循环线程 有100个线程  ,它们的优先级相同,其它99个线程有空闲的也有不是空闲的。 运行之后,cpu

根据时间片来执行这些线程,每当执行完某个线程的部分代码即将要进入空闲状态时,这个空的死循环会不断的向cpu申请资源,cpu立即去执行这个空的死循环,导致cpu没有空闲的状态,最后会100%   (cpu从一个线程切换到另一个线程,也要消耗cpu)。

打个比方,现在有一个环卫工人,负责打扫5条街,本来是打扫完一条街可以休息10分钟(一条街40分钟内没有垃圾)。但是现在由于第二条街人口剧增,每当环卫工人准备休息的时候,街道办就打电话来说赶紧去打扫第二条街,如此一来环卫工人再也没有休息的时间了。

 

 

 

最后 由于春运快到了,给大家安利一个抢火车票的小程序心到抢票,微信扫码关注点击立即抢票即可

个人亲测效率很高,大家也可以加他们官方微信  xdticket  咨询。

<think>嗯,用户现在要求的是用图画演示JDK NIO的epoll bug导致Selector轮询的机制。这个问题挺专业的,涉及到Java NIO底层和Linux epoll的交互细节。 从用户提供的引用来看,特别是引用4提到了Netty的解决方案,引用5解释了轮询的原因,用户似乎已经对这个问题有一定了解,现在需要更直观的理解方式。考虑到技术问题的抽象性,用文字描述流程图可能是最合适的方案。 需要重点展现几个关键节点:Selector初始轮询状态、连接异常中断后的错误状态、Linux epoll的误通知、Selector的持续轮询循环。每个环节都要对应到CPU使用率的变化上,特别是最后100%的那个状态。 在描述时需要特别注意: 1. 区分操作系统层(epoll)和JVM层(Selector)的交互 2. 强调异常中断时SelectionKey的状态异常 3. 展示Netty解决方案的介入点(rebuiltSelector) 用户可能是系统调优工程师或者中间件开发者,遇到实际性能问题才这么深入追究。ta连续追问NIO底层问题,说明不是初学者,回答需要保持技术严谨性。 要不要补充说明这个bug在后续JDK版本的变化?不过用户明确要求图示演示,这些文字说明可能作为备注更合适。最终决定把版本影响放在流程图说明里简单带过。 最后生成的问题要覆盖Netty替代方案、监控诊断、现代JDK情况等延伸方向,这样既解答当前问题又提供后续研究路径。 </think>以下是 JDK NIO 的 `epoll bug` 导致 `Selector` 轮询及 CPU 100% 问题的图示化分析: --- ### **Selector 轮询问题流程图** ```mermaid graph TD A[Selector 开启轮询] --> B{是否有 I/O 事件?} B -->|无事件| C[轮询发生] B -->|有事件| D[正常处理] C --> E{检测轮询次数} E -->|连续轮询 > 阈值| F[触发 epoll bug] E -->|未达阈值| A F --> G[Selector 持续轮询] G --> H[线程占用 CPU 100%] ``` --- ### **关键步骤解析** 1. **Selector 初始轮询** - 当应用程序调用 `selector.select()` 时,底层通过 `epoll_wait` 监听 I/O 事件。 - 正常情况:若无事件,线程应阻塞(进入休眠状态)[^1][^2]。 2. **异常中断触发轮询** - **问题根源**:当 TCP 连接被异常中断(如 RST 报文)时,Linux epoll 可能错误地唤醒 `Selector`,但实际无就绪事件[^3][^4]。 - **结果**:`selector.select()` 立即返回 `0`(表示无事件),却未阻塞线程。 3. **CPU 100% 形成机制** ```mermaid flowchart LR S[Selector 轮询] --> L{轮询循环} L -->|select 立即返回 0| L L --> T[线程持续占用 CPU] ``` - 由于 `Selector` 未进入阻塞状态,线程进入死循环调用 `select()`,CPU 时间被无限占用[^1][^5]。 4. **JDK 未彻底修复的原因** - JDK 1.6 update18 后仅降低了触发频率,但未解决 epoll 内核层的误唤醒问题[^2][^4]。 - `SelectionKey` 未定义“连接异常中断事件”,导致内核异常无法被应用层捕获[^5]。 --- ### **Netty 的解决方案** ```plaintext 原始流程: Selector.select() → 轮询 → CPU 100% Netty 改进: Selector.select() → 检测轮询次数 → 若超阈值 ↓ 重建 Selector (替换旧实例) ↓ 迁移 Channel 到新 Selector ``` - **核心逻辑**:统计 `select()` 调用次数与返回 `0` 的次数,若轮询比例超过阈值(如 512 次),触发 `rebuildSelector()` [^3][^4]。 - **优势**:通过重建 `Selector` 重置内核事件表,规避持续轮询。 --- ### **影响范围** | 系统/场景 | 触发概率 | 后果 | |--------------------|---------------|--------------------| | 高并发 TCP 服务器 | 高(连接频繁中断) | 单线程 CPU 100% | | 长连接服务 | 中 | 线程池资源耗尽 | | UDP 服务 | 低 | 几乎不触发 | --- ### **规避建议** 1. **升级 JDK**:JDK 17+ 优化了 `Selector` 实现,显著降低触发概率[^5]。 2. **使用 Netty**:其内置的 `NioEventLoop` 自动处理轮询(默认阈值 512 次)[^3][^4]。 3. **监控指标**:检测线程 CPU 使用率及 `selector.select()` 返回次数。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值