package com.hxh;
public class hungry
public static hungry getinstance()
public static void main(string args) ).start();}}
}
注意事項:變數hungry必須是:私有,靜態,不可變;
構造器私有;
公開的
getinstance
方法,使外界可以獲取變數。
package com.hxh;
public class lazyman
public static lazyman getinstance()
return lazyman;
}public static void main(string args) }}
輸出如下,單執行緒下看起來毫無問題:
lazyman被建立修改main函式,改為多執行緒com.hxh.lazyman@39a054a5
com.hxh.lazyman@39a054a5
com.hxh.lazyman@39a054a5
com.hxh.lazyman@39a054a5
com.hxh.lazyman@39a054a5
com.hxh.lazyman@39a054a5
com.hxh.lazyman@39a054a5
com.hxh.lazyman@39a054a5
com.hxh.lazyman@39a054a5
com.hxh.lazyman@39a054a5
public static void main(string args) ).start();}}
從上圖可以看出,一共建立了4個物件,並不是單例的。
通過修改獲取例項方法getinstance
,給物件加鎖解決上面的問題:
public static lazyman getinstance() }}
return lazyman;
}
輸出如下:
lazyman被建立現在看起來好像並沒有什麼問題。但是com.hxh.lazyman@33ca79ec
com.hxh.lazyman@33ca79ec
com.hxh.lazyman@33ca79ec
com.hxh.lazyman@33ca79ec
com.hxh.lazyman@33ca79ec
com.hxh.lazyman@33ca79ec
com.hxh.lazyman@33ca79ec
com.hxh.lazyman@33ca79ec
com.hxh.lazyman@33ca79ec
com.hxh.lazyman@33ca79ec
lazyman = new lazyman();
這並不是乙個原子性操作,極端情況下可能會發生指令重排,那麼什麼是指令重排呢?
指令重排:解決辦法也很簡單,為jvm建立物件分為三步:
分配記憶體空間
執行構造方法、建立例項
將記憶體與例項關聯
問題就出現在上面的步驟中,我們所預期的步驟是123,而編譯器有時為了優化效能,會選擇其他的順序執行上面的步驟。在單執行緒下沒有影響,而多執行緒時就會出現問題,如:
執行緒a執行步驟為132;
執行緒b執行步驟為123;
lazyman
物件新增volatitle
關鍵字,保證不會出現指令重排
完整**如下:
package com.hxh;
public class lazyman
public static lazyman getinstance() }}
return lazyman;
}public static void main(string args) ).start();}}
}
01 設計模式 單例模式
package com.hxh public class hungry public static hungry getinstance public static void main string args start 注意事項 變數hungry必須是 私有,靜態,不可變 構造器私有 公開的get...
設計模式 01單例設計模式
所謂類的單例設計模式,就是採取一定的方法保證在整個軟體系統中,對某個類只能存在乙個物件例項,並且該類只提供乙個取得其物件例項的方法 靜態方法 比如hibernate中的sessionfactory,它充當的就是資料儲存源的 並負責建立session物件。sessionfactory並不是輕量級的,一...
設計模式星火01 單例模式
1 用單例的時機 需要保證乙個類只有乙個例項,並且提供乙個他的全域性訪問點。2 方法 2.1 將建構函式定義為保護型別的 使用者沒有辦法建立物件 2.2 向類中新增兩個靜態成員 乙個靜態成員函式和乙個私有靜態成員變數 static classname m pinstance static class...