餓漢式
// final 不允許被繼承
public final class Singleton {
// 餓漢式,先new
private static Singleton singleton = new Singleton();
// 私有構造不允許外部 new
private Singleton(){
}
public static Singleton getInstance(){
return singleton;
}
}
餓漢式的問題是 instance 在被 ClassLoader加載後很長時間才能在使用,如果類中的資源是重資源,那麼就必須使用懶漢式
懶漢式
// final 不允許被繼承
public final class Singleton {
// 餓漢式,先new
private static Singleton singleton = null;
// 私有構造不允許外部 new
private Singleton(){
}
public static Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
問題是多線程下不能保證實例的唯一性。
懶漢式+ 同步
// 但是 只允許一個 線程 訪問這個方法 ,效率就會很低
// final 不允許被繼承
public final class Singleton {
// 餓漢式,先new
private static Singleton singleton = null;
// 私有構造不允許外部 new
private Singleton(){
}
public static synchronized Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
Double-check
//
// final 不允許被繼承
public final class Singleton {
// 餓漢式,先new
// 不加 volatile 可能出現空指針異常 ,可能JVM指令的重排序
private volatile static Singleton singleton = null;
// 私有構造不允許外部 new
private Singleton(){
}
// 雙重校驗,可以進入方法
public static Singleton getInstance(){
if (singleton == null){
synchronized(Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
Holder 實現靜態的私有內部類
// final 不允許被繼承
public final class Singleton {
// 私有構造不允許外部 new
private Singleton(){
}
private static class Holder{
private static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return Holder.instance;
}
}
Singleton 類中,初始化過程中並不會創建 Singleton 的實例 ,只有當 Holder 類被主動引用的時候則會創建
枚舉方式
枚舉的方式不允許被繼承,同時是線程安全的 ,只能被實例化一次
推薦使用枚舉的方式
餓漢式
public enum Singleton {
INSTANCE;
// 私有構造不允許外部 new
private Singleton(){
System.out.println("Instance will be init immediately");
}
//
public static Singleton getInstance(){
return INSTANCE;
}
}
// 懶加載
把枚舉作爲內部類進行懶加載
public class Singleton {
private Singleton(){
}
private enum EnumHolder{
INSTANCE;
private Singleton instance;
EnumHolder(){
this.instance = new Singleton();
}
private Singleton getInstance(){
return instance;
}
}
public static Singleton getInstance(){
return EnumHolder.INSTANCE.getInstance();
}
}