1.單例模式定義:確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例(Ensure a class has only one instance, and provide a global point of access to it).
2.單例模式好處:對於需要頻繁創建和銷燬的對象使用單例模式可以節省開銷,對於重量級對象而言性能十分明顯。減輕GC的壓力,從而縮短GC停頓時間。
3. 單例模式通用代碼
public class Singleton {
private static Singleton singleton=new Singleton();
private Singleton(){}
public static Singleton getSingleton()
{
return singleton;
}
public static void doSometing(){} //類中其他方法儘量使static
}
4.單例模式使用場景和注意事項
適用於要求生成唯一序列號的環境或整個項目中需要一個共享訪問點。單例模式在高併發情況下,由於對象初始化需要時間,所以當一個線程尚未初始化完畢的時候,另一個線程也會進行初始化,所以便產生了多個對象。
5.單例模式優化
(1).調用時創建。對於上述通用的創建方法,在虛擬機加載此類的初始化階段,就會創建此類對象的實例從而產生一定的負載,爲了減少類初始化時候的時間可以在調用的時候再調用構造器。
public class Singleton {
private static Singleton singleton=null; //初始化階段賦Null 所以不會進行實例化
private Singleton(){}
public static Singleton getSingleton() //當發生調用的時候纔會實例化。
{
if(singleton==null)
{
singleton=new Singleton();
}
return singleton;
}
public static void doSometing(){}
}
(2). 併發下同步。由於單例模式並不是線程安全的所以在多併發情況下對其同步變得十分必要
通過不變量保證線程安全。
public class Singleton {
private static final Singleton singleton=new Singleton();
//將產生的實例設置爲不變量,並在JVM加載的時候進行初始化。
private Singleton(){}
public static Singleton getSingleton()
{
return singleton;
}
public static void doSometing(){}
}
使用synchronized關鍵字。由於使用同步關鍵字是重量級的同步所以對性能將產生很大的影響。public class Singleton {
private static Singleton singleton=null;
private Singleton(){}
public static synchronized Singleton getSingleton() //使用同步關鍵字進行方法級同步
{
if(singleton==null)
{
singleton=new Singleton();
}
return singleton;
}
public static void doSometing(){}
}
通過內部類來同步。內部類由於在JVM加載類的時候才初始化實例,所以天生多線程友好,同時又保持了調用時實例化的特性。
public class Singleton {
private static Singleton singleton=null;
private Singleton(){}
//內部類在發生調用的時候纔開始加載並且在加載的時候就進行一次初始化所以線程安全。
private static class SingletonHolder{private static Singleton instance =new Singleton();}
public static Singleton getSingleton()
{
return SingletonHolder.instance;
}
public static void doSometing(){}
}
6.注意
單例模式依然有許多會被破壞的情況 如:通過反射調用私有構造函數,單例的串行化和反串行化等。
單例模式會與單一職責原則有衝突。具體是否使用單例要看項目所處的環境和目標。