什麼是單例模式?
單例模式顧名思義就是單個實例。比如各種Mgr,各種Factory,這樣的一個項目裏只需要有一個實例存在。話雖如此,我們封裝了這樣一個東西給別人用時,難保別人不會去new很多對象出來。所以,我們完全可以在代碼上保證他,只有一個實例存在。這就是單例模式。
常見的兩種形式
餓漢模式
示例代碼
public class Single01 {
private static final Single01 INSTANCE = new Single01();
//私有的構造方法,外部無法new對象
private Single01() {
}
public static Single01 getInstance() {
return INSTANCE;
}
}
這裏我們根據上面的定義來測試一下,是否只有一個實例存在
public static void main(String[] args) {
Single01 single01 = Single01.getInstance();
Single01 single011 = Single01.getInstance();
System.out.println(single01 == single011);
}
輸出結果爲:true
結論:該方式編寫的單例模式,只有一個實例存在
懶漢模式
示例代碼
public class Single02 {
private static Single02 INSTANCE;
private Single02() {
}
private static Single02 getInstance() {
if (INSTANCE == null) {
INSTANCE = new Single02();
}
return INSTANCE;
}
}
再來看下這形式的是否依然滿足 只有一個實例存在
private static Single02 getInstance() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//此處線程不安全
if (INSTANCE == null) {
INSTANCE = new Single02();
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(() -> System.out.println(Single02.getInstance().hashCode())).start();
}
}
我們知道在同一個類中同一個對象的hashCode是相同的。
輸出結果:存在hashCode不一致的情況
結論
懶漢模式,在多線程的情況下,會重複new對象。所以我們在使用單例模式的時候,最好使用第一種形式。