概念
單例模式是指保證某個(gè)類在整個(gè)軟件系統(tǒng)中只有一個(gè)對(duì)象實(shí)例,并且該類僅提供一個(gè)返回其對(duì)象實(shí)例,由于單例模式在內(nèi)存中只有一個(gè)實(shí)例,減少了內(nèi)存開支,特別是一個(gè)對(duì)象需要頻繁地創(chuàng)建、銷毀時(shí),而且創(chuàng)建或銷毀時(shí)性能又無(wú)法優(yōu)化,單例模式的優(yōu)勢(shì)就非常明顯。
在計(jì)算機(jī)系統(tǒng)中,線程池、緩存、日志對(duì)象、對(duì)話框、打印機(jī)、顯卡的驅(qū)動(dòng)程序?qū)ο蟪1辉O(shè)計(jì)成單例。選擇單例模式是為了避免不一致狀態(tài)。
單例常見方式
餓漢式(線程安全)
餓漢就是類一旦加載,單例初始化就開始,保證在調(diào)用getInstance()方法時(shí),單例是已經(jīng)存在的了,以后不再改變,所以是線程安全的。
缺點(diǎn):當(dāng)類裝載的時(shí)候就會(huì)創(chuàng)建類的實(shí)例,不管你用不用,都會(huì)先創(chuàng)建出來(lái),無(wú)法做到延遲創(chuàng)建對(duì)象,從而降低內(nèi)存的使用率。
/*
餓漢單例模式設(shè)計(jì):
①使用private修飾構(gòu)造函數(shù),限制了外部創(chuàng)建該類對(duì)象
②創(chuàng)建一個(gè)靜態(tài)的對(duì)象,在類初始化時(shí),已經(jīng)自行實(shí)例化。
③聲明一個(gè)getInstance方法來(lái)返回該靜態(tài)對(duì)象
*/
public class SingletonPattern {
private static final SingletonPattern single=new SingletonPattern();
private SingletonPattern(){}
static public SingletonPattern getInstance(){
return single;
}
}
懶漢式(線程不安全)
懶漢模式中,在第一次調(diào)用的時(shí)候?qū)嵗约海簿褪钦f只有當(dāng)調(diào)用getInstance()的時(shí)候,并且判斷 instance為null時(shí)才創(chuàng)建一個(gè)實(shí)例。被動(dòng)地創(chuàng)建實(shí)例。
/*設(shè)計(jì):
①構(gòu)造函數(shù)私有,避免外部創(chuàng)建對(duì)象(但是Java反射機(jī)制是能夠?qū)嵗瘶?gòu)造方法為private的類的,會(huì)使Java單例實(shí)現(xiàn)失效)
②聲明當(dāng)前類的引用,此時(shí)不能對(duì)引用進(jìn)行實(shí)例化
③聲明getInstance()方法,懶漢式單例的實(shí)現(xiàn)沒有考慮線程安全問題, 它是線程不安全的,并發(fā)環(huán)境下可能出現(xiàn)多個(gè)實(shí)例,要保證線程安全,可以使用 synchronized將方法聲明為同步方法,雙重檢查鎖定,或者靜態(tài)內(nèi)部類,根據(jù)當(dāng)前對(duì)象判斷是否為null來(lái)創(chuàng)建對(duì)象。
*/
線程不安全的懶漢式
public class SingletonPattern2 {
private static SingletonPattern2 singe=null;
private SingletonPattern2(){}
public static SingletonPattern2 getInstance(){
if (singe==null){
singe=new SingletonPattern2();
}
return singe;
}
}
線程安全的懶漢式
1、在getInstance方法上加同步
public class SingletonPattern2 {
private static SingletonPattern2 singe=null;
private SingletonPattern2(){}
public synchronized static SingletonPattern2 getInstance(){
if (singe==null){
singe=new SingletonPattern2();
}
return singe;
}
}
2、雙重檢查鎖定
public class SingletonPattern2 {
private static SingletonPattern2 singe=null;
private SingletonPattern2(){}
public synchronized static SingletonPattern2 getInstance(){
if (singe==null){
synchronized (SingletonPattern2.class){
if (singe==null){
singe=new SingletonPattern2();
}
}
}
return singe;
}
}
3、靜態(tài)內(nèi)部類
public class SingletonPattern2 {
private SingletonPattern2(){}
public static class LazyHolder{
private static SingletonPattern2 singe=new SingletonPattern2();
}
public static SingletonPattern2 getInstance() {
return LazyHolder.singe;
}
}
測(cè)試
public class Test {
public static void main(String[] args) {
//餓漢式(線程安全)
SingletonPattern instance =SingletonPattern.getInstance();
SingletonPattern instance2 =SingletonPattern.getInstance();
//判斷是否是一個(gè)對(duì)象實(shí)例
System.out.println(instance==instance2);//true
//懶漢式(線程不安全)
SingletonPattern2 instance3 =SingletonPattern2.getInstance();
SingletonPattern2 instance4 =SingletonPattern2.getInstance();
//判斷是否是一個(gè)對(duì)象實(shí)例
System.out.println(instance3==instance4);//true
}
}
懶漢式和餓漢式區(qū)別
餓漢式天生就是線程安全的,可以直接用于多線程而不會(huì)出現(xiàn)問題,
懶漢式本身是非線程安全的,為了實(shí)現(xiàn)線程安全有以上幾種寫法。
懶漢模式和餓漢模式的實(shí)例創(chuàng)建的時(shí)機(jī)不同;
單例模式的應(yīng)用場(chǎng)景
某類只要求生成一個(gè)對(duì)象的時(shí)候,如一個(gè)班中的班主任。
單例模式為一個(gè)面向?qū)ο蟮膽?yīng)用程序提供對(duì)象惟一的訪問點(diǎn),整個(gè)應(yīng)用程序同享一個(gè)實(shí)例對(duì)象。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-548879.html
某類需要頻繁實(shí)例化,而創(chuàng)建的對(duì)象又頻繁被銷毀的時(shí)候,如多線程的線程池文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-548879.html
到了這里,關(guān)于單例模式(懶漢式和餓漢式)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!