什么会导致 Java 应用程序的 CPU 使用率飙升?,spring 快速入门教程
1.如何计算 CPU 使用率?
CPU%= 1 - idleTime / sysTime * 100
idleTime:CPU 空闲的
时间
sysTime:CPU 处于用户模式和内核模式的时间总和
2.与 CPU 使用率有关的是什么?
人们常说,计算密集型程序的 CPU 密集程度更高。
那么,JAVA 应用程序中的哪些操作更加 CPU 密集?
以下列出了常见的 CPU 密集型操作:
频繁的 GC; 如果访问量很高,可能会导致频繁的 GC 甚至 FGC。当调用量很大时,内存分配将如此之快以至于 GC 线程将连续执行,这将导致 CPU 飙升。
序列化和反序列化。稍后将给出一个示例:当程序执行 xml 解析时,调用量会增加,从而导致 CPU 变满。
序列化和反序列化;
正则表达式。 我遇到了正则表达式使 CPU 充满的情况; 原因可能是 Java 正则表达式使用的引擎实现是 NFA 自动机,它将在字符匹配期间执行回溯。我写了一篇文章“ 正则表达式中的隐藏陷阱 ”来详细解释原因。
线程上下文切换; 有许多已启动的线程,这些线程的状态在 Blocked(锁定等待,IO 等待等)和 Running 之间发生变化。当锁争用激烈时,这种情况很容易发生。
有些线程正在执行非阻塞操作,例如 while (true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。
3. CPU 是否与进程和线程相关?
现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用 CPU 资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在 CPU 中也是分时的。但在 Java 中,我们使用 JVM 进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。
答案
1. while 的无限循环会导致 CPU 使用率飙升吗?
是。
首先,无限循环将调用 CPU 寄存器进行计数,此操作将占用 CPU 资源。那么,如果线程始终处于无限循环状态,CPU 是否会切换线程?
除非操作系统时间片到期,否则无限循环不会放弃占用的 CPU 资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。
2.频繁的 Young GC 会导致 CPU 占用率飙升吗?
是。
Young GC 本身就是 JVM 用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的 Young GC 必须占用 CPU 资源。
让我们来看一个现实世界的案例。for 循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM 将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到 CPU 使用率警报。
3.具有大量线程的应用程序的 CPU 使用率是否较高?
不时。
如果通过 jstack 检查系统线程状态时线程总数很大,但处于 Runnable 和 Running 状态的线程数不多,则 CPU 使用率不一定很高。
我遇到过这样一种情况:系统线程的数量是 1000+,其中超过 900 个线程处于 BLOCKED 和 WAITING 状态。该线程占用很少的 CPU。
但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于 BLOCKED 和 WAITING 状态。
4.对于 CPU 占用率高的应用程序,线程数是否较大?
不是。
高 CPU 使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则 CPU 使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。
5.处于 BLOCKED 状态的线程是否会导致 CPU 占用率飙升?
不会。
CPU 使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致 CPU 使用率上升。
6.如果分时操作系统中 CPU 的值 us 或 sy 值很高,这意味着什么?
您可以使用命令查找 CPU 的值 us 和 sy 值 top,如以下示例所示:
评论