一、CPU 和线程的基本概念
1. 什么是 CPU?
- **CPU(中央处理器)**是计算机的核心硬件,负责执行所有的计算和指令。
- 现代服务器通常有多个物理核心(Core),每个核心可以独立处理任务。
- 有些 CPU 支持超线程(Hyper-Threading) ,一个物理核心可以模拟成两个“逻辑核心”,提升并发能力。
2. 什么是线程?
- 线程是操作系统调度的最小单位,是程序中实际被 CPU 执行的“工作单元”。
- 一个进程可以包含多个线程,这些线程可以并发执行。
- 线程的状态包括:新建(New)、就绪(Ready)、运行(Running)、阻塞/等待(Blocked/Waiting)、终止(Terminated)。
3. 线程与 CPU 的关系
- 线程需要被 CPU 核心调度执行,一个线程在某一时刻只能被一个核心执行。
- N核 CPU,同一时刻最多只能有 N 个线程被真正“运行”,其余线程处于等待(就绪)或阻塞状态。
- 操作系统通过“时间片轮转”让多个线程轮流获得 CPU 执行权,实现“多任务并发”。
二、线程和 CPU 占用的关系
1. 能占用 CPU 的是线程
- 只有处于“就绪”或“运行”状态的线程才会消耗 CPU。
- 阻塞/等待状态(如等待 IO、锁、sleep)的线程不会占用 CPU。
2. 线程数和 CPU 占用的关系
- 线程多≠CPU占用高,关键看有多少线程在“忙碌”地执行。
- 少量线程如果每个都在高强度计算,也能让 CPU 占用升高。
- 线程多但大部分在等待(如 IO 阻塞),CPU 占用可能很低。
3. 线程的“就绪”状态
- 线程已经具备运行条件,只是暂时没有被分配到 CPU。
- 一旦有空闲核心,调度器会立刻让其运行。
三、什么情况下会导致 CPU 占用升高?
1. 代码层面
- 死循环或递归:线程陷入无限循环,持续占用 CPU。
- 高频轮询:频繁轮询数据库、消息队列、外部接口,没有等待或限流。
- 大量并发请求:短时间内大量请求,线程池满载,CPU 资源被耗尽。
- 频繁垃圾回收(GC) :内存泄漏或对象创建过多,导致 GC 线程频繁运行。
- 复杂计算任务:如加密、压缩、大数据处理等。
2. 外部依赖或环境
- 依赖服务响应慢:调用外部服务超时,线程堆积,CPU 被消耗。
- 数据库慢查询:数据库响应慢,应用线程等待,间接引发 CPU 飙高。
- 恶意攻击或爬虫:被恶意流量刷接口,导致 CPU 飙升。
3. 服务器层面
- 资源竞争:多个进程/服务争抢 CPU。
- 系统任务异常:如病毒、异常进程等。
四、CPU 100% 时服务的可用性
1. CPU 100% 说明什么?
- 说明服务器所有 CPU 核心都被占满,系统资源耗尽。
- 操作系统调度变慢,应用响应变慢甚至无响应。
- 可能导致请求超时、服务不可用、健康检查失败等。
2. CPU 100% 时服务还可用吗?
- 理论上,服务还能处理请求,但响应会极慢,用户体验极差。
- 实际上,大多数情况下服务会出现超时、错误,甚至完全不可用。
- 健康检查和监控通常会报警,部分云平台会自动重启或下线实例。
3. CPU 100% 服务是不是 down 掉了?
- 不一定完全 down,但大概率“不可用”或“极不稳定”。
- 轻则响应慢、超时,重则完全无响应,健康检查失败被摘除。
五、如何排查和优化 CPU 占用高的问题?
-
查看线程数和线程状态
- Linux 下用
top
、htop
、ps -efL
,或 Java 的jstack
。
- Linux 下用
-
分析热点代码
- 用 Java 的
jstack
、jvisualvm
、arthas
等工具分析线程堆栈。
- 用 Java 的
-
检查 GC 日志
- 频繁 GC 也会导致 CPU 高。
-
优化代码和架构
- 避免死循环、合理限流、优化算法、减少不必要的并发。
-
扩容或分布式部署
- 增加服务器或核心数,分散压力。
六、总结
- CPU 是硬件,线程是操作系统调度的单位。
- N核 CPU 同时只能执行 N 个线程,其余线程排队等待。
- CPU 占用高通常是线程“忙碌”导致的,线程多但大部分阻塞不会导致 CPU 高。
- CPU 100% 时服务大概率不可用或极不稳定,需要及时排查和优化。