系統優化貫穿需求、設計、編碼、維護全生命周期。本文結合實戰案例,從對象創建策略與循環編寫細節兩大高頻維度,提煉出具體可落地的優化條例。
| 類型 | 定義 | 典型場景 | 優/缺點 | 選型建議 |
|---|---|---|---|---|
| 獨享對象 | 單線程擁有,new 創建,線程結束 GC | 請求級 Bean、DTO、VO | 線程安全無需同步,但增加內存與 GC 壓力 | 生命周期短、含可變狀態、不願共享 |
| 共享對象 | 多線程共享,工廠/單例獲取 | 配置屬性、工具類、DAO、Service | 節省內存,但需同步控制併發 | 生命周期長、創建開銷大、狀態不可變或線程安全 |
| 不變對象 | 無 setter,狀態構造後凍結 | String、常量對象、值對象 | 天然線程安全、無副作用、可自由共享 | 屬性少、創建開銷小、需廣泛共享 |
| 方法對象 | 僅含方法無屬性 | Util、DAO、Service 統一入口 | 可用 static 方法或單例,避免重複 new | 操作其他對象、無自身狀態、職責單一 |
ThreadLocal 或每次 new// 反向循環刪除:避免 ArrayList 每次 remove(0) 觸發大量 arraycopy
for (int i = list.size() - 1; i >= 0; i--) {
if (shouldRemove(list.get(i))) list.remove(i);
}
原理:ArrayList.remove(index) 需 System.arraycopy 移動後續元素。從尾部刪除 numMoved=0,僅置 null,效率指數級優於正向刪除。
實測數據(10萬次循環):正向 ~6000ms,反向 ~15ms。
ArrayList:隨機訪問快,增刪慢(需移動/擴容)LinkedList:雙向鏈表,增刪快(只改指針),隨機訪問慢經典陷阱:讀取 InputStream 循環未檢查 read() == -1 導致死循環佔滿 CPU。
// 錯誤寫法
for (; totalRead < m_totalBytes; totalRead += readBytes) {
readBytes = in.read(buf, totalRead, m_totalBytes - totalRead);
}
// 正確寫法
while (totalRead < m_totalBytes) {
readBytes = in.read(buf, totalRead, m_totalBytes - totalRead);
if (readBytes == -1) break; // 關鍵防禦
totalRead += readBytes;
}
循環必須明確:規模、每次耗時、正常結束條件、異常結束條件(EOF、異常、超時)。
// 差
for (int i=0; i
addBatch() + executeBatch() 替換循環 executeUpdate()addAll()、removeAll()、retainAll() 替換手動循環對象復用與循環優化看似微小,卻是高併發、大數據量系統性能的基石。建議:
下一篇將探討數據庫訪問優化、緩存策略、鎖優化等進階主題。