單例模式幾種寫法,安全 不安全 懶漢 餓漢
單例模式在平常中運用較多,而且在面試中更是被經常提及
單例模式有幾個重點是懶漢模式,餓漢模式,線程安全,線程不安全
這個是最普通的單例模式,這個是懶漢式,線程不安全
//這個是普通的單例模式
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if (instance === null) {
instance = new Singleton();
}
return instance;
}
}
**懶漢式,線程安全類型**
//這個是線程安全的單例模式
//這個在調用的時候回鎖住整個方法,效率不是很好
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static synchronized getInstance(){
if (instance === null) {
instance = new Singleton();
}
return instance;
}
}
雖然這個是線程安全,但是效率不是很好,因為在任何時候只有一個線程能調用getInstance()方法。
下面我們就使用雙重檢驗鎖來解決這個問題。
雙重檢驗鎖是對同步塊加鎖的方法。為什么會稱為雙重檢驗,因為有兩次對 instance == null的檢查,一次中同步塊中一次中同步塊外部。
為什么在同步塊內還要再檢驗一次?因為可能會有多個線程一起進入同步塊外的 if,如果在同步塊內不進行二次檢驗的話就會生成多個實例了。
//這個是線程安全的是效率比較好的
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if (instance == null) {
synchronized(Singleton.class){
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
上面的不是都是懶漢模式的,下面我們來介紹一下關於餓漢模式的
餓漢模式 static final field 這種方法也是很簡單,只需要將單例的實例聲明為static何final變量。這是因為在第一次加載到內存中的就會被初始化,所以創建實例本身是線程安全的。
public class Singleton{
//類加載時就初始化
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
**靜態內部類 stat nested class**
//懶漢式的靜態內部類
public class Singleton{
private static class SingletonInner{
private static final Singleton INSTANCE = new Singleton();
}
private Singleton{
}
private static final Singleton getInstance(){
return SingletonInner.INSTANCE**strong text**;
}
}
這是目前最好的解法,既是線程安全又無其他的問題。