1、餓漢式單例
private Singleton() { }
public static Singleton getInstance() {
return INSTANCE;
}
}
2、借助內(nèi)部類
屬于懶漢式單例,因?yàn)镴ava機(jī)制規(guī)定,內(nèi)部類SingletonHolder只有在getInstance()方法第一次調(diào)用的時(shí)候才會(huì)被加載(實(shí)現(xiàn)了lazy),而且其加載過(guò)程是線程安全的。內(nèi)部類加載的時(shí)候?qū)嵗淮蝘nstance。
private static class SingletonHolder {
private final static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
3、普通加鎖解決
private Singleton() { }
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
雖然解決了線程安全問(wèn)題,但是每個(gè)線程調(diào)用getInstance都要加鎖,我們想要只在第一次調(diào)用getInstance時(shí)加鎖,請(qǐng)看下面的雙重檢測(cè)方案
4、雙重檢測(cè),但要注意寫法
private Singleton() { }
public static Singleton getInstance() {
if(instance == null) {
synchronzied(Singleton.class) {
Singleton temp = instance;
if(temp == null) {
temp = new Singleton();
instance = temp
}
}
}
return instance;
}
}
由于指令重排序問(wèn)題,所以不可以直接寫成下面這樣:
public class Singleton {
private static Singleton instance = null;
private Singleton() { }
public static Singleton getInstance() {
if(instance == null) {
synchronzied(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
但是如果instance實(shí)例變量用volatile修飾就可以了,volatile修飾的話就可以確保instance = new Singleton();對(duì)應(yīng)的指令不會(huì)重排序,如下的單例代碼也是線程安全的:
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() { }
public static Singleton getInstance() {
if(instance == null) {
synchronzied(Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
新聞熱點(diǎn)
疑難解答
圖片精選