首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 代碼效能優化實戰指南:從入門到精通

     編輯:Java 相關知識

優化核心原則

測量優於猜測,可讀性優於微優化,架構優於局部。
—— 任何優化前請先 Profiling(JProfiler、Async Profiler、Arthas),找到真正熱點再下手。

15 條高頻優化模式

一、對象創建與復用

1. 字串拼接:StringBuilder/StringBuffer 代替 +

// ❌ 迴圈中產生大量臨時 String 對象
String result = "";
for (String s : list) result += s;

// ✅ 單線程用 StringBuilder,多線程用 StringBuffer
StringBuilder sb = new StringBuilder(list.size() * 16); // 預估容量
for (String s : list) sb.append(s);
String result = sb.toString();

原理: + 編譯器雖優化為 StringBuilder,但迴圈中每次仍 new Builder + toString,產生大量短命對象,增加 Young GC 壓力。

2. 局部變量優於成員/靜態變量

// ✅ 棧上分配,隨棧幀銷毀,無 GC 開銷
void process() {
    String prefix = "gebi"; // 局部變量
    if ("laowang".equals(name)) {
        list.add(prefix + name);
    }
}

原理: 局部變量存棧,生命週期隨方法結束;堆上對象需 GC 回收,分配/回收皆有開銷。

3. 迴圈外提取不變量、避免重複創建

// ❌ 每次迴圈 new Object()
while (i < 1000) { Object obj = new Object(); }

// ✅ 引用復用,僅分配 1 個引用變量
Object obj = null;
while (i < 1000) { obj = new Object(); }

二、集合與流操作

4. 集合初始化指定容量

// ✅ 避免多次擴容複製
List<User> users = new ArrayList<>(expectedSize);
Map<Long, Order> map = new HashMap<>((int)(expectedSize / 0.75f) + 1);

5. Map 遍歷:entrySet 優於 keySet

// ✅ 單次查找,O(1)
for (Map.Entry<K, V> entry : map.entrySet()) {
    K k = entry.getKey(); V v = entry.getValue();
}

// ❌ keySet 需再 map.get(key),雙重查找
for (K k : map.keySet()) { V v = map.get(k); }

6. 大數據量遍歷:Iterator vs forEach

  • 極致效能: Iterator(避免隱式 lambda 物件、棧幀開銷)
  • 可讀性/維護性: forEach / Stream API
  • 建議: 百萬級以上用 Iterator;業務代碼優先可讀性。

三、I/O 與資源管理

7. 必須使用緩衝流

// ✅ BufferedInputStream/Reader 包裹,減少系統調用
try (BufferedReader br = new BufferedReader(new FileReader(file))) { ... }

8. 及時關閉流、連接、線程池

使用 try-with-resources 確保釋放,避免句柄洩漏導致系統資源耗盡。

四、異常與控制流

9. 異常不用於控制流、不在迴圈內 try-catch

// ❌ 迴圈內 try-catch,JIT 難優化、棧追蹤開銷大
for (Item item : items) {
    try { process(item); } catch (Exception e) { log(e); }
}

// ✅ 迴圈外統一捕獲,或 process 內部處理
try {
    for (Item item : items) process(item);
} catch (Exception e) { log(e); }

10. try-catch 範圍最小化

僅包裹可能拋檢查異常的代碼,避免污染熱點路徑的 JIT 優化(如內聯、逃逸分析)。

五、關鍵字與鎖優化

11. 謹慎使用 static

  • static 變量生命週期 = 類生命週期,持有大對象導致記憶體洩漏(如單例持有大 List)。
  • 常量用 static final,編譯器常量折疊優化。

12. 鎖粒度最小化、用無鎖結構

// ✅ 細粒度鎖
private final Object lock = new Object();
public void update() {
    synchronized (lock) { /* 僅保護共享狀態 */ }
}

// ✅ 高併發用 ConcurrentHashMap、LongAdder、ThreadLocal
ConcurrentHashMap<K, V> map = new ConcurrentHashMap<>();
LongAdder counter = new LongAdder(); // 優於 AtomicLong

六、JVM 與進階

13. 逃逸分析與標量替換

JDK 8+ 預設開啟 -XX:+DoEscapeAnalysis,未逃逸對象可標量替換(拆解為局部變量)、棧上分配、同步消除。寫法:方法內 new 對象、不傳遞給外部。

14. 基本類型優於包裝類

// ✅ 避免裝箱/拆箱開銷
int sum = 0;
for (int i = 0; i < 10000; i++) sum += i;

// ❌ Integer 自動裝箱拆箱
Integer sum = 0;
for (int i = 0; i < 10000; i++) sum += i;

15. 包裝類 toString 效能排序

Integer i = 1;
// 效能:i.toString() > String.valueOf(i) > "" + i
// 原因:""+i 編譯為 StringBuilder.append(i).toString(),多一次 Builder 創建

優化檢查清單

類別檢查項工具/驗證
對象分配熱點方法分配率、大對象直接進老年代JProfiler / Async Profiler / arthas heapdump
GCYoung/Old GC 頻率、停頓時間、記憶體佔用曲線GC Log + GCViewer / Arthas dashboard
鎖爭用同步塊耗時、阻塞線程數JProfiler Monitor / Arthas thread -b
I/O系統調用次數、緩衝區大小strace / perf / Java Flight Recorder
JIT熱點方法編譯狀態、內聯情況-XX:+PrintCompilation / JITWatch

總結

  1. 先測量,再優化:無 Profiling 不優化。
  2. 大刀闊斧: 演算法/資料結構/架構層面優化收益 >> 微優化。
  3. 守底線: 不犧牲可讀性、正確性換取微小效能增益。
  4. 持續迭代: 優化是過程,而非一次性任務;配合壓測、基準測試驗證。

掌握這 15 條模式,配合工具驅動優化,你的 Java 代碼將在效能與可維護性間達到最佳平衡。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved