在23個標準設計模式中,單例模式在應用中還是很常見的,但是在多執行緒環境中,單例模式的使用有非常多的坑,使用好單例模式的乙個原則:如何使單例模式在遇到多執行緒的環境中是安全的、正確的。下面分析幾種多執行緒的實現方式以及遇到的坑。
立即載入:實用類的時候已經將物件建立完畢,常見的是直接new例項化,有「著急」,「急迫」的意思,因此也稱:「餓漢模式」。在呼叫方法前,已經例項化物件。**如下:
單例模式:
public執行緒:class
singleton01
public
static
singleton01 getinstance()
}
public測試類:class mythread extends
thread
}
public執行結果:class
run
}
所有執行緒的物件hashcode均是一樣的,證明是單例模式,but,該**的實現是優缺點的:不能有其他例項變數,因為getinstance方法沒有同步,可能會出現執行緒安全問題。
延遲載入:在呼叫方法的時候,物件才被例項化,常用的實現方式就是在方法內部例項化物件。**如下:
單例模式:
public執行緒類:class
singleton02
public
static
singleton02 getinstance()
return
instance;}}
public測試類:class mythread extends
thread
}
public執行結果:class
run
}
從執行結果來看,控制台列印了多個hashcode值,說明該實現方式在多執行緒的環境中是失敗的,如何解決呢?其實很簡單,讓方法同步即可,使用synchronized關鍵字。改進後**吐下:
public再次執行:class
singleton02
synchronized
public
static
singleton02 getinstance()
} catch
(interruptedexception e)
return
instance;}}
同步之後,證明該單例模式是正確的。但是,這種方式又帶來一種缺點,那就是效率問題,因為下乙個執行緒必須需要等上乙個執行緒釋放鎖之後才能執行,需要排隊執行,因此還可以優化,那就是:嘗試同步**塊,針對重要**進行單獨同步,以提公升效率。
下面總結了一種使用dcl雙檢查鎖機制實現單例模式,該模式適用於在多執行緒環境中的延遲載入單例模式設計。**如下:
public這種方式既保證了執行緒的安全性,還保證了效率。class
singleton03
public
static
singleton03 getinstance()}}
} catch
(interruptedexception e)
return
instance;}}
前面的改進方式可以實現在多執行緒的環境中實現單例模式,並且保證執行緒安全,那麼這種靜態內建類的方式也可以實現同樣的效果。建立靜態內類,如下:
public執行緒類:class
singleton04
public
singleton04()
public
static
singleton04 getinstance()
}
public測試類同上class mythread extends
thread
}
執行結果:
靜態內建類固然可以實現單例模式,但是這裡有乙個坑,那就是在遇到序列化和反序列化的時候,依然會出現問題,依然會出現多個例項化物件,**如下:
單例模式
public序列化執行類:class singleton05 implements
serializable
public
singleton05()
public
static
singleton05 getinstance()
}
public執行結果:class
run2
catch
(ioexception e)
//讀try
catch (ioexception |classnotfoundexception e)
}
很明顯,寫入和讀出來的物件不是乙個,顯然不符合單例模式的設計模式。序列化破壞了單例模式,當然,還有一種破壞單例模式的方式,那就是反射,單例模式中盡量不要使用反射。呢麼問題來了,如何改進呢,其實很簡單,在序列化的時候在呼叫乙個方法。改進如下:
public再次執行:class singleton05 implements
serializable
public
singleton05()
public
static
singleton05 getinstance()
protected object readresolve()throws
objectstreamexception
}
序列化操作提供了乙個很特別的鉤子(hook)-類中具有乙個私有的被例項化的方法readresolve(),這個方法可以確保類的開發人員在序列化將會返回怎樣的object上具有發言權。這樣就確保我們在反序列化的時候返回的物件是同乙個。
靜態**塊中的**執行實在實用類的時候載入,因此我們可以應用靜態**塊的這種特性來設計單例模式。**如下:
public執行緒類測試類同三,結果如下:class
singleton06
static
public
static
singleton06 getinstance()
}
}測試執行類同上,結果如下:
特點就是實現非常簡單。
多執行緒(4)單列模式
單列模式分為兩種 餓漢式 package util public class single public static single getsingle 懶漢式 package util public class single public static single getsingle retur...
終於理解單列模式了,單列模式和多執行緒
1 單例類確保自己只有乙個例項 構造方法私有化 2 單例類必須自己建立自己的例項。3 單例類必須為其他物件提供唯一的例項。package singleton 懶漢式 單例例項在第一次被使用時構建,延遲初始化。public class singleton return sing public void...
c 單列模式與執行緒安全
通常c 裡面的單列模式很容易實現,我們也不需要去考慮其執行緒安全的問題,但是在多執行緒環境中我們卻必須要考慮到。首先我們來分析下一下的這個單列模式為什麼不是執行緒安全的,通常的單列模式寫法 class msgofarrival msgofarrival msgofarrival m pinstanc...