1. JVM線程優化 1.1. 當空間不足時,可以調整線程使用的記憶體 1.2. 每個線程都有一個原生棧,操作系統會在這裡存儲線程的調用棧信息 1.3. 原生棧的大小是1 MB 1.3.1. 32位的Windows JVM原生棧大小是320KB 1.3.2. 在64位的JVM中,通常不會修改這個值 1 ...
1. JVM線程優化
1.1. 當空間不足時,可以調整線程使用的記憶體
1.2. 每個線程都有一個原生棧,操作系統會在這裡存儲線程的調用棧信息
1.3. 原生棧的大小是1 MB
-
1.3.1. 32位的Windows JVM原生棧大小是320KB
-
1.3.2. 在64位的JVM中,通常不會修改這個值
- 1.3.2.1. 除非機器的物理記憶體相當緊張
-
1.3.3. 較小的棧大小可以防止應用程式用完原生記憶體
-
1.3.3.1. 許多程式可以在棧大小為256 KB時運行
-
1.3.3.2. 很少有程式需要用到完整的1 MB
-
1.4. -Xss=N標誌
- 1.4.1. 改變線程的棧大小
2. 原生記憶體溢出
2.1. 在32位的JVM中,進程使用的記憶體達到了4 GB(或者小於4 GB,取決於操作系統)的最大大小
2.2. 系統實際已經耗盡虛擬記憶體
2.3. 減小棧的大小可以解決
2.4. 在Unix風格的系統上,用戶創建的進程(他們正在運行的所有程式)已經達到了此次登錄配置的最大進程數
- 2.4.1. 單個線程被認為是一個進程
2.5. 無法從JVM的異常中判斷是這三種情況中的哪一種
3. 偏向鎖
3.1. 讓鎖偏向於最近訪問鎖的線程
- 3.1.1. 如果一個線程最近使用了某個鎖,那麼下次它執行被同一個鎖保護的代碼時,處理器的緩存更有可能還包含該線程需要的數據
3.2. 但是偏向鎖需要簿記信息,所以有時機器性能會更糟糕
3.3. 使用線程池的應用程式(包括某些應用程式和REST伺服器)在偏向鎖生效時,往往表現得更差
3.4. -XX:-UseBiasedLocking
-
3.4.1. 禁用偏向鎖
-
3.4.2. 預設開啟的
4. 線程優先順序
4.1. 每個Java線程都有一個由開發人員定義的優先順序,這是對操作系統的一種提示,用來說明程式認為特定線程有多重要
4.2. 操作系統會為機器上運行的每個線程計算一個當前優先順序
-
4.2.1. 當前優先順序既考慮了Java分配的優先順序,也考慮了許多其他因素
-
4.2.2. 最重要的因素是線程上次運行到現在有多長時間
-
4.2.3. 無論其優先順序如何,都不會有線程因為等待訪問CPU而“饑餓”
4.3. 在Windows上,Java優先順序較高的線程往往比優先順序較低的線程運行得更多,但即使是低優先順序的線程也會獲得相當多的CPU時間
4.4. 無論在哪種情況下,都不能依賴線程的優先順序來決定它的運行頻率
4.5. 如果某些任務比其他任務更重要,就必須使用應用程式邏輯來確定它們的優先順序
5. 監控線程和鎖
5.1. 線程的總數
-
5.1.1. 通過系統提供的基本線程信息可以大致瞭解運行的線程數量
-
5.1.2. 確保它不會太高或太低
5.2. 查看線程信息可以確定線程被阻塞的原因
-
5.2.1. 它們在等待資源
-
5.2.2. 它們在等待I/O
5.3. 查看線程
-
5.3.1. jconsole
- 5.3.1.1. 顯示JVM內的線程狀態
5.4. 查看阻塞線程
-
5.4.1. Java飛行記錄器JFR
-
5.4.1.1. 可以查看JVM內部、並能在底層知道線程何時被阻塞
-
5.4.1.2. 提供了一個簡單的方法來檢查導致線程阻塞的事件
-
-
5.4.2. jstack
-
5.4.2.1. 提供虛擬機中每個線程的狀態信息,包括線程是否在運行、是否在等待鎖、是否在等待I/O
-
5.4.2.2. 在一定程度上可以查看線程阻塞在什麼資源上
-
-
5.4.3. 大量的阻塞線程會降低性能。不管是什麼原因造成的阻塞,都需要改變配置或應用程式,以避免阻塞
6. 線程性能沒有太多可以優化
6.1. 可以調整的JVM標誌相對較少
6.2. 這些標誌的效果也十分有限
6.3. 良好的線程性能最佳實踐準則
-
6.3.1. 管理線程數
-
6.3.2. 限制同步影響