是什么使Java应用程序的CPU使用率飙升()

本文概述

  • 问题
  • 思维
  • 答案
  • 经验
问题
无限循环会导致CPU使用率飙升吗?频繁使用Young GC是否会导致CPU使用率飙升?具有大量线程的应用程序的CPU使用率是否很高?对于CPU使用率高的应用程序, 线程数是否大?处于阻塞状态的线程会导致CPU使用率飙升吗?分时操作系统中的CPU是否消耗us或sy?
思维 1.我们如何计算CPU使用率?
CPU%= 1-idleTime / sysTime * 100
  • idleTime:CPU空闲的时间
  • sysTime:CPU处于用户模式和内核模式时的时间总和
2.与CPU使用率有什么关系?
【是什么使Java应用程序的CPU使用率飙升()】人们常说计算密集型程序占用的CPU更多。
那么, JAVA应用程序中的哪些操作会占用更多CPU资源?
以下是有关常见的CPU密集型操作的列表:
频繁的GC; 如果访问量很高, 可能会导致频繁的GC甚至FGC。当调用数量很大时, 内存分配将是如此之快, 以至于GC线程将被连续执行, 这将导致CPU飙升。
序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时, 调用数量增加, 这将导致CPU变满。
加密和解码;
正则表达式。
我遇到过这样的情况, 正则表达式使CPU满了。原因可能是Java正则表达式使用的引擎实现是NFA自动机, 它将在字符匹配期间执行回溯。我写了一篇文章
正则表达式中的隐藏陷阱
”详细解释原因。
线程上下文切换;有许多启动线程, 并且这些线程的状态在“阻塞”(锁定等待, IO等待等)和“持续运行”之间变化。当锁争用很激烈时, 这种情况很容易发生。
一些线程正在执行非阻塞操作, 例如
而(真)
陈述。如果在程序中计算需要很长时间, 则可以使线程休眠。
3. CPU与进程和线程有关吗?
现在, 分时操作系统使用循环方式为进程调度分配时间片。如果该进程正在等待或阻塞, 则它将不使用CPU资源。线程称为轻型进程, 并共享进程资源。因此, 线程调度在CPU中也是分时的。但是在Java中, 我们使用JVM进行线程调度。因此, 通常有两种线程调度模式:分时调度和抢占式调度。
答案 1. while的无限循环会导致CPU使用率飙升吗?
是。
首先, 无限循环将调用CPU寄存器进行计数, 此操作将占用CPU资源。那么, 如果线程始终处于无限循环状态, CPU会切换线程吗?
除非操作系统时间片到期, 否则无限循环不会放弃占用的CPU资源, 并且无限循环将继续向系统请求时间片, 直到系统没有空闲时间来执行其他任何操作为止。
在stackoverflow中也曾问过这个问题:为什么一个意想不到的无限循环会增加CPU使用率?
https://stackoverflow.com/questions/2846165/why-does-an-infinite-loop-of-the-unintended-kind-increase-the-cpu-use
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值很高, 那意味着什么?
你可以使用top命令找到CPU的us和sy值, 如以下示例所示:
是什么使Java应用程序的CPU使用率飙升()

文章图片
us:用户空间占用CPU的百分比。简单来说, 高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。 sy:内核空间占用CPU的百分比。当sy高时, 如果它是由程序引起的, 则基本上是由于线程上下文切换引起的。
经验 如何定位CPU占用率高的原因?分析过程在下面简要描述。
如果发现应用服务器的CPU使用率很高, 请首先检查诸如线程数, JVM, 系统负载等参数, 然后使用这些参数来证明问题的原因。其次, 使用jstack打印堆栈信息, 并使用工具分析线程使用情况(建议使用在线线程分析工具fastThread)。
以下是实际情况:
一天晚上, 突然, 我收到一条消息, 指出CPU使用率达到100%。因此, 我立即转储了用jstack打印的堆栈信息, 并通过http://fastthread.io/查看了日志。
是什么使Java应用程序的CPU使用率飙升()

文章图片
进一步检查特定日志:
consumer_ODC_L_nn_jmq919_1543834242875 - priority:10 - threadid:0x00007fbf7011e000 - nativeid:0x2f093 - state:RUNNABLEstackTrace:java.lang.Thread.State:RUNNABLEat java.lang.Object.hashCode(Native Method)at java.util.HashMap.hash(HashMap.java:362)at java.util.HashMap.getEntry(HashMap.java:462)at java.util.HashMap.containsKey(HashMap.java:449)at com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)at com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)at com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28)at com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)

啊哈, 我现在通过此日志找到了问题所在:用于反序列化MQ消息实体的方法导致CPU使用率猛增。

    推荐阅读