保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
單例模式(Singleton)的目的是為了保證在一個進程中,某個類有且僅有一個實例。
- 餓漢式
在聲明之初就指定對象實例化。
public class Singleton {
// 靜態(tài)字段引用唯一實例:
private static final Singleton INSTANCE = new Singleton();
// private構(gòu)造方法保證外部無法實例化:
private Singleton() {
}
// 通過靜態(tài)方法返回實例:
public static Singleton getInstance() {
return INSTANCE;
}
}
2.懶漢式
在真正調(diào)用的時候才實例化對象。
public class Singleton {
private static Singleton INSTANCE = null;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
在單線程下這種懶漢式是沒有問題的,但是在多線程下這種方式是線程不安全的,餓漢式會有JVM實例化替我們保證線程安全,懶漢式要進行以下改造。
public class Singleton {
private static volatile Singleton INSTANCE = null;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
為什么要這么做呢?
因為實例化表面上看起來是一個語句,但是里面涉及到了分配內(nèi)存空間,初始化對象,將對象指向剛分配的內(nèi)存空間的操作。有些編譯器為了性能的原因,可能會將第二步和第三步進行重排序,那么使用volatile后重排序被禁止,所有的寫(write)操作都將發(fā)生在讀(read)操作之前。
3.內(nèi)部類
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
內(nèi)部類這種形式支持懶加載,也線程安全,推薦使用