(願歲月清淨)
單例模式: 確保乙個類最多只有乙個例項,提供乙個全域性訪問點
注意:
單例模式可以分為兩種:
1.預載入(餓漢式)
預先載入。還沒有使用該單例物件,但是該單例物件就已被載入到記憶體。
public
class
hungry
;public
static hungry getinstance()
}
若沒有使用該單例物件,該物件就被載入到了記憶體,會造成記憶體的浪費。
2.懶載入(懶漢式)
為了避免記憶體的浪費,可以採用懶載入,即用到該單例物件的時候再建立。
public
class
lazy
;public
static lazy getinstance()
return instance;
}}
3. 單例模式和執行緒安全
餓漢式只有一條語句return instance,可以保證執行緒安全。但會造成記憶體的浪費。
懶漢式不浪費記憶體,但是無法保證執行緒的安全。首先,if判斷以及其記憶體執行**是非原子性的。其次,new singleton()無法保證執行的順序性。不滿足原子性或者順序性,執行緒肯定是不安全的,不再贅述。
為什麼new singleton()無法保證順序性。建立乙個物件分三步:
memory=
allocate()
;//1:初始化記憶體空間
ctorinstance
(memory)
;//2:初始化物件
instance=
memory()
;//3:設定instance指向剛分配的記憶體位址
jvm為了提高程式執行效能,會對沒有依賴關係的**進行重排序,上面2和3行**可能被重新排序。我們用兩個執行緒來說明執行緒是不安全的。執行緒a和執行緒b都建立物件。其中,a2和a3的重排序,將導致執行緒b在b1處判斷出instance不為空,執行緒b接下來將訪問instance引用的物件。此時,執行緒b將會訪問到乙個還未初始化的物件(執行緒不安全)。
4. 懶漢式的執行緒安全解決方法
使用synchronized關鍵字。synchronized載入getinstace()函式上確實保證了執行緒的安全。
注意:若要經常的呼叫getinstance()方法,不管有沒有初始化例項,都會喚醒和阻塞執行緒。為了避免執行緒的上下文切換消耗大量時間,如果物件已經例項化了,我們沒有必要再使用synchronized加鎖,直接返回物件。
public
class
lazy
;public
static
synchronized lazy getinstance()
return instance;
}}
把sychronized加在if(instance==null)判斷語句裡面,保證instance未例項化的時候才加鎖
public
class
lazy
;public
static
synchronized lazy getinstance()
}}return instance;
}}
new乙個物件的**是無法保證順序性的,需要使用關鍵字volatile保證物件例項化過程的順序性。
public
class
lazy
;public
static
synchronized lazy getinstance()
}}return instance;
}}
即保證了懶漢式的執行緒安全。 23種設計模式 單例模式
某些情況,如 執行緒池,乙個專案中匯流排程數量以及生命週期,可能需要統一控制 如果執行緒池自身可建立多個例項,那麼就無法統一控制,此時,只要能控制線程池物件的數量為乙個,那麼就可以實現統一控制的目標 注意 現實中真正使用純的單例模式並不多 如 spring bean 通過配置來決定是否使用單例 執行...
單例模式(23種設計模式)
單例模式 餓漢模式 class singletondemo public static singletondemo gets 懶漢模式 class singletondemo1 public static singletondemo1 gets return instance 單例模式,懶漢式,執行...
23種設計模式 單例模式
單例模式需要保證,構造方法一定是私有化的,並且類的全域性變數必須是靜態的,私有的 這樣才能有唯一的例項化途徑 錯誤 一 public class singleton public static singleton getinstance 上述方法,並沒有把類變數singleton設定為靜態的,這樣,...