java效能調優記錄

高石柯南發表於2024-10-06

五、設計模式調優

單例模式

最簡單的單例模式及問題分析

// 懶漢模式
public final class Singleton {
private static Singleton instance= null;// 不例項化
private Singleton(){

if (instance != null) {
throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
}

}// 建構函式
public static Singleton getInstance(){// 透過該函式向整個系統提供例項
if(null == instance){// 當 instance 為 null 時,則例項化物件,否則直接返回物件
instance = new Singleton();// 例項化物件
}
return instance;// 返回已存在的物件
}
}

問題分析:存在多次例項化的可能,多個執行緒同時修改不同單例物件可能導致資料不一致,因為單例物件可能持有計數器或者配置項等。

先建立的物件會不會被jvm垃圾回收?

可能會,前提是沒有被其他物件引用,如建立並使用他的執行緒結束,該物件就不會被引用,下一次垃圾回收就會回收掉。

雙重檢查方式:

// 懶漢模式 + synchronized 同步鎖 + double-check
public final class Singleton {
private volatile static Singleton instance= null;// 不例項化
private Singleton(){

if (instance != null) {
throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
}

}// 建構函式
public static Singleton getInstance(){// 加同步鎖,透過該函式向整個系統提供例項
if(null == instance){// 第一次判斷,當 instance 為 null 時,則例項化物件,否則直接返回物件
synchronized (Singleton.class){// 同步鎖
if(null == instance){// 第二次判斷
instance = new Singleton();// 例項化物件
}
}
}
return instance;// 返回已存在的物件
}
}

雙重檢查模式的變數需要用volatile,volatile有兩個作用:可見性,禁止指令重排序。

靜態內部類方式:

// 懶漢模式 內部類實現
public final class Singleton {

// 建構函式
private Singleton() {

if (InnerSingleTon.instance != null) {
throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
}

}
// 內部類實現
public static class InnerSingleton {
private static Singleton instance=new Singleton();// 自行建立例項
}

public static Singleton getInstance() {
return InnerSingleton.instance;// 返回內部類中的靜態變數
}
}

靜態內部類和外部類的載入是獨立的,外部類被載入時,靜態內部類不會被立即載入。靜態內部類只有在被主動引用時(例如建立靜態內部類的例項或訪問其靜態成員)才會被載入。同樣地,當靜態內部類被載入時,它也不會導致外部類重新載入或初始化。

裝飾器模式

六、資料庫效能調優

快照讀:當執行普通的select時,mysql不會加鎖,而是讀取資料庫快照,在整個事務生命週期都是獲取同一個快照資料,不糊收到其他事務更新或插入影響。快照並不是事務開始時的快照,而是第一次普通查詢時被鎖定的快照。

但是並不是每次查詢結果不會變,如事務B插入一條原本不存在的資料,事務A修改了這條資料,此時事務A再查詢是可以查到的。

當前讀:當讀取的是需要加鎖的的操作,讀取的是當前最新資料,當前讀會阻止其他事務對被鎖住的資料進行修改,並確保你看到的是最新的、當前事務的狀態。

  • SELECT ... FOR UPDATE
  • SELECT ... LOCK IN SHARE MODE
  • UPDATEDELETE

間隙鎖:需要注意mysql查詢又間隙鎖,即使只查詢一條資料如order_no=4,資料分佈是1,3,6,8,那麼會鎖定3到6之間的間隙,這種操作可以防止3-6之間的幻讀。但是大於6的資料如7,20都是可以在另一個事務B中正常插入的,並且事務A中可以查到。

分庫分表:

分為水平拆分和垂直拆分:水平拆分是把資料分佈在不同庫上,垂直拆分是指把表欄位再進行拆分。

分散式鎖:redis官方推出的redisson框架。

相關文章