單例模式是一種常用的設計模式,單例對象通常作爲程序中的存放配置信息的載體,以保證其他對象讀到一致的信息。
在某個服務器程序中,服務器的配置信息可能存放在數據庫或文件中,其他對象要取得這些信息只需要訪問這個單例就可以。
這個機制在單線程環境下實現簡單,在多線程環境下需要考慮同步問題。
首先,通常使用惰性加載的機制,在單例對象使用的時候纔去創建。
public class Singleton{
private static Singleton instance=null;
Private Singleton(){
......
}
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
return instance;
}
}
這樣當第一次調用時單例才被創建。
double-checked locking
對於getInstance()方法,通過對其添加synchronized塊來處理同步問題。
public static Singleton getInstance(){
if(instance==null){
synchronized(instance){
if(instance==null)
instance=new Singleton();
}
return instance;
}
沒有將synchronized加到方法名前,所以同步代碼段只會在最開始執行。
從JVM的角度講,上述代碼仍然可能發生錯誤。在Java指令中創建對象和賦值操作時分開進行的。(指令重排序問題)
假設有線程A和B調用getInstance(),線程A在執行到創建對象步驟後離開,當B進入時instance已經不是null了,但卻還沒有初始化。
用volatile修飾instance的話就可以確保instance = new Singleton();對應的指令不會重排序。
還有一種使用內部類的方式:
- public class Singleton{
- private Singleton(){
- …
- }
- private static class SingletonContainer{
- private static Singleton instance = new Singleton();
- }
- public static Singleton getInstance(){
- return SingletonContainer.instance;
- }
-
}