單例模式:java中用到的 Java.lang.Runtime
整個應用中只維護一個特定類實例,它被所有組件共同使用。
1:構造方法私有化
2:提供了一個靜態方法,供外界獲取它的靜態實例
靜態方法分餓漢式,懶漢式
餓漢式:類加載時就初始化,浪費內存,線程安全
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
懶漢式:使用的時候加載,通常線程不安全,需要另外處理
普通的懶漢式 線程不安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
synchronized的加鎖的懶漢式 線程安全,但加鎖影響效率:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
雙重檢測的懶漢式, singleton == null 檢測兩次,
懶加載,線程安全
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}}}
return singleton; }
}
登記式靜態內部類:
線程安全,懶加載,SingletonHolder 只有枚舉實現單例
面試的時候推崇這個,完全挑不出毛病的,但是這種寫法比較生疏
自動支持序列化機制,絕對防止多次實例化,實現原理是Java規範字規定,每個枚舉類型及其定義的枚舉變量在JVM中都是唯一的
public enum Singleton {
INSTANCE;
public void whateverMethod() {
//do something
}
}
講真:這個我有點懵逼了
INSTANCE,肯定是單例的,
但我的對象呢? 其實換個寫法就可以
public enum Singleton {
INSTANCE;
private int age = 0; //屬性
private Singleton() {
System.out.println("這裏是初始化方法");
age = 100;
}
public void whateverMethod() {
System.out.println("單例執行");
System.out.println(age);
}
}
INSTANCE 就是對象,有屬性,有方法
請注意多線程操作單例對象的屬性時,會出現線程安全問題,
多線程調用單例的同一個方法,不會出現堵塞,是併發執行的
參見: https://blog.csdn.net/xy3233/article/details/106433638