這六種原因,真能讓 Java 應用 CPU 使用率飆升至 100% 嗎?
- 2020 年 2 月 19 日
- 筆記
點擊上方「碼農沉思錄」,選擇「設為星標」
優質文章,及時送達
問題
1、無限循環的while會導致CPU使用率飆升嗎? 2、經常使用Young GC會導致CPU佔用率飆升嗎? 3、具有大量執行緒的應用程式的CPU使用率是否較高? 4、CPU使用率高的應用程式的執行緒數是多少? 5、處於BLOCKED狀態的執行緒會導致CPU使用率飆升嗎? 6、分時作業系統中的CPU是消耗 us
還是 sy
?
思路
1.如何計算CPU使用率?
CPU%= 1 – idleTime / sysTime * 100
idleTime:CPU空閑的時間
sysTime:CPU處於用戶模式和內核模式的時間總和
2.與CPU使用率有關的是什麼?
人們常說,計算密集型程式的CPU密集程度更高。
那麼,JAVA應用程式中的哪些操作更加CPU密集?
以下列出了常見的CPU密集型操作:
1、頻繁的GC; 如果訪問量很高,可能會導致頻繁的GC甚至FGC。當調用量很大時,記憶體分配將如此之快以至於GC執行緒將連續執行,這將導致CPU飆升。 2、序列化和反序列化。稍後將給出一個示例:當程式執行xml解析時,調用量會增加,從而導致CPU變滿。 3、序列化和反序列化; 4、正則表達式。我遇到了正則表達式使CPU充滿的情況; 原因可能是Java正則表達式使用的引擎實現是NFA自動機,它將在字元匹配期間執行回溯。 5、執行緒上下文切換; 有許多已啟動的執行緒,這些執行緒的狀態在Blocked(鎖定等待,IO等待等)和Running之間發生變化。當鎖爭用激烈時,這種情況很容易發生。 6、有些執行緒正在執行非阻塞操作,例如 while(true)
語句。如果在程式中計算需要很長時間,則可以使執行緒休眠。
3、CPU是否與進程和執行緒相關?
現在,分時作業系統使用循環方式為進程調度分配時間片。如果進程正在等待或阻塞,那麼它將不會使用CPU資源。執行緒稱為輕量級進程,並共享進程資源。因此,執行緒調度在CPU中也是分時的。但在Java中,我們使用JVM進行執行緒調度。因此,通常,執行緒調度有兩種模式:時間共享調度和搶佔式調度。
答案
1、while的無限循環會導致CPU使用率飆升嗎?
是。
首先,無限循環將調用CPU暫存器進行計數,此操作將佔用CPU資源。那麼,如果執行緒始終處於無限循環狀態,CPU是否會切換執行緒?
除非作業系統時間片到期,否則無限循環不會放棄佔用的CPU資源,並且無限循環將繼續向系統請求時間片,直到系統沒有空閑時間來執行任何其他操作。整編:微信公眾號,搜雲庫技術團隊,ID:souyunku
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
值很高,這意味著什麼?
您可以使用命令查找CPU的值 us
和 sy
值 top
,如以下示例所示:

us
:用戶空間佔用CPU的百分比。簡單來說,高我們是由程式引起的。通過分析執行緒堆棧很容易找到有問題的執行緒。整編:微信公眾號,搜雲庫技術團隊,ID:souyunku
sy
:內核空間佔用CPU的百分比。當sy為高時,如果它是由程式引起的,那麼它基本上是由於執行緒上下文切換。
經驗
如何找出CPU使用率高的原因?下面簡要描述分析過程。
如果發現應用程式伺服器的CPU使用率很高,請首先檢查執行緒數,JVM,系統負載等參數,然後使用這些參數來證明問題的原因。其次,使用jstack列印堆棧資訊並使用工具分析執行緒使用情況(建議使用fastThread,一個在線執行緒分析工具)。
以下是一個真實案例:
一天晚上,我突然收到一條消息,說CPU使用率達到了100%。然後我用jstack導出了執行緒棧資訊。

進一步檢查日誌:
onsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE stackTrace: java.lang.Thread.State:RUNNABLE at java.lang.Object.hashCode(NativeMethod) 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使用率飆升。
新年快樂,祝福送到,好運來到,問候也到。祝願你新年新氣象,事業步步高;快樂總依然,心情永遠好;幸福總綿綿,生活永遠好,注意點個再看哦。