原創文章,轉載請標註出處:https://www.cnblogs.com/V1haoge/p/10755322.html
一、概述
Java中單例有7種寫法,這個是在面試中經常被問到的內容,而且有時候還要求手寫單例實現方式。所以我們有必要認真的瞭解一下這七種寫法。
二、七種實現
2.1 懶漢式——執行緒不安全
public class SingletonOne {
public static SingletonOne singleton;
private SingletonOne() {}
public static SingletonOne getSingleton() {
if (singleton == null)
return new SingletonOne();
return singleton;
}
}
懶漢式實現了懶載入,但是執行緒不安全,基本不會使用。
2.2 懶漢式——執行緒安全
public class SingletonTwo {
public static SingletonTwo singleton;
private SingletonTwo() {}
public static synchronized SingletonTwo getSingleton() {
if (singleton == null)
return new SingletonTwo();
return singleton;
}
}
在第一種的基礎上加了個synchronized,保證執行緒安全,同時實現了懶載入,只是效率不高。
2.3 餓漢式
public class SingletonThree {
public static SingletonThree singleton = new SingletonThree();
private SingletonThree () { }
public static SingletonThree getSingleton() {
return singleton;
}
}
由於例項優先提供,不存線上程安全問題,但是沒有實現懶載入。
2.4 餓漢式——變種
public class SingletonFour {
public static SingletonFour singleton;
static {
singleton = new SingletonFour();
}
private SingletonFour () { }
public static SingletonFour getSingleton() {
return singleton;
}
}
其實和之前的一樣,僅僅是將單例的建立挪到了靜態塊。
2.5 靜態內部類式
public class SingletonFive {
private static class SingletonHolder {
private static SingletonFive singleton = new SingletonFive();
}
private SingletonFive () {}
public static final SingletonFive getSingleton(){
return SingletonHolder.singleton;
}
}
靜態內部類保證了懶載入,單例例項優先提供又保證了執行緒安全性,較實用。
2.6 列舉式
public enum SingletonSix {
SINGLETON;
}
列舉的天然特性保證了單例,天然的私有構造器,天然的執行緒安全性,未被大規模使用的原因是列舉出現的有點晚。
2.7 雙重校驗鎖式
public class SingletonSeven {
private static volatile SingletonSeven singleton;
private SingletonSeven() {}
public static SingletonSeven getSingleton(){
if (singleton == null) {
synchronized (SingletonSeven.class) {
if (singleton == null)
return new SingletonSeven();
}
}
return singleton;
}
}
注意:
- volatile的使用,為了防止暴露一個未初始化的不完整單例例項;
- 雙重判空校驗,第一個判斷避免了頻繁的加鎖,第二個判斷可以攔住多餘的建立例項的執行緒;
- 加鎖,保證了執行緒安全(只有一個例項)
這種實現方式是經常出現在面試題中的,而且經常會要求手寫。
三、總結
上面羅列的7種設計模式中第1種執行緒不安全,可以排除在外,第3、4種其實是一種,這樣下來其實可以簡化為5種方式:懶漢、餓漢、靜態內部類、列舉、雙重校驗鎖。