public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance ;
}
}
//頁面計數器
public class PageCounter {
private static final PageCounter instance = new PageCounter();
// 計數器
private AtomicLong counter = new AtomicLong(0);
private PageCounter() {
}
public static PageCounter getInstance() {
return instance ;
}
public void add() {
counter.getAndAdd(1);
}
public long get() {
return counter.get();
}
}
//餓漢模式(推薦),類加載時就創建了
//優點:1、線程安全;2、調用getInstance時速度快
//缺點:1、無法延遲加載;2、有可能浪費資源,無人調用getInstance()時,仍然創建了實例
public class Singleton01 {
private static final Singleton01 instance = new Singleton01();
private Singleton01() {
}
public static Singleton01 getInstance() {
return instance ;
}
}
第二種(餓漢變種)//餓漢模式變種,類加載時就創建了,和上一個模式區別不大,只是能在static中加入邏輯處理
public class Singleton02 {
private static Singleton02 instance = null;
static {
// 此處可以寫一些邏輯
instance = new Singleton02();
}
private Singleton02() {
}
public static Singleton02 getInstance() {
return instance ;
}
}
第三種(懶漢)//懶漢(線程不安全),用到了再去初始化
//優點:延遲加載
//缺點:致命的併發問題,可能導致創建多次
public class Singleton03 {
private static Singleton03 instance = null;
private Singleton03() {
}
public static Singleton03 getInstance() {
if ( instance == null ) {
// 此處有併發問題
instance = new Singleton03();
}
return instance ;
}
}
第四種(懶漢變種)//懶漢(線程安全)
//優點:延遲加載
//缺點:效率低下,初始化完畢後,getInstance()方法根本不需要同步了
public class Singleton04 {
private static Singleton04 instance = null;
private Singleton04() {
}
public synchronized static Singleton04 getInstance() {
if ( instance == null ) {
instance = new Singleton04();
}
return instance ;
}
}
第五種(雙重鎖定檢查)//雙重鎖定檢查
//優點:延遲加載,效率高
//缺點:jdk1.5之後纔可以用
//由於jdk1.5之前編譯器允許處理器亂序執行,所以可能導致獲取到沒初始化完畢的instance
public class Singleton05 {
private static Singleton05 instance = null;
private Singleton05() {
}
public static Singleton05 getInstance() {
if ( instance == null ) {
synchronized (Singleton05.class) {
if ( instance == null ) {
instance = new Singleton05();
}
}
}
return instance ;
}
}
第六種(枚舉)//枚舉方式(推薦),Effective Java作者Joshua Bloch推薦的方式
//優點:不僅能避免線程同步問題,還能防止反序列化生成新的對象,相當嚴謹
//最主要的是非常的簡單
//缺點:枚舉是jdk1.5之後加入的特性,對版本有要求
public enum Singleton06 {
instance;
public void someMethod() {
// 業務邏輯方法
}
}
第七種(靜態內部類) //靜態內部類
//優點:解決線程安全問題,而且可以延遲加載,基本上是曾經最好的辦法
//缺點:代碼複雜
public class Singleton07 {
private static class RealSingleton {
static final Singleton07 instance = new Singleton07();
}
public static Singleton07 getInstance() {
return RealSingleton.instance;
}
}
單例模式創建方法有很多種,沒有最好的,只有最合適的,比如第七種方法比較好,但是沒必要爲了一個不會出現的問題而使用很複雜的第七種模式,如果沒有需要延遲加載的地方(如讀取配置文件等),推薦第一種模式,如果是JDK1.5以上,推薦使用枚舉的方法。5、能夠處理多ClassLoader、多JVM,防止反序列化等情況。