單列設計模式

單列中的四種實現方式

方式一:普通的餓漢式和懶漢式單例模式

三部曲:java

(1)私有化構造方法
(2)私有化靜態本類對象做爲屬性
(3)提供公有靜態方法獲取本類對象

 1.普通的餓漢式(靜態的內部)安全

public class Client {
    public static void main(String[] args) {
        Singleton.getInstance();
    }

    static class Singleton {
        private static final Singleton instance = new Singleton();

        private Singleton(){}

        public static Singleton getInstance(){
            return  instance;
        }

    }
}

2.餓漢式靜態代碼塊單例模式併發

//餓漢式靜態代碼塊單例模式
public class HungryStaticSingleton {
    private static final HungryStaticSingleton instance;

    static {
        instance = new HungryStaticSingleton();
    }

    private HungryStaticSingleton(){}

    public static HungryStaticSingleton getInstance(){
        return  instance;
    }
}

3.餓漢式靜態代碼塊單例模式ide

/**
 * 優勢:執行效率高,性能高,沒有任何的鎖
 * 缺點:某些狀況下,可能會形成內存浪費
 */
//餓漢式靜態代碼塊單例模式
public class HungrySingleton {

    private static final HungrySingleton instance = new HungrySingleton();

    private HungrySingleton(){}

    public static HungrySingleton getInstance(){
        return  instance;
    }
}

二:懶漢式

1.懶漢式單例模式在外部須要使用的時候才進行實例化,這種是線程不安全的,若是多個線程同時併發訪問,假設多個線程同時都進入到了 if(instance == null){}條件判斷裏面,那麼就會同時建立多個對象。性能

/**
 * 優勢:節省了內存,線程安全
 * 缺點:性能低
 */
//懶漢式單例模式在外部須要使用的時候才進行實例化
public class LazySimpleSingletion {
    //靜態塊,公共內存區域
    private static LazySimpleSingletion instance;

    private LazySimpleSingletion(){}

    public synchronized static LazySimpleSingletion getInstance(){
        if(instance == null){
            instance = new LazySimpleSingletion();
        }
        return instance;
    }
}

2.單次檢查機制(使用類鎖),這種也是有缺點的,使用的 synchronized 關鍵字,嚴重的影響了性能.this

public class Singleton {
    private static Singleton instance = null;
    public  static Singleton getInstance() {
        synchronized (Singleton.class) {
            if(null == instance) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

3.利用雙重檢查機制(DCL) ,保證了線程的安全spa

/**
 * 優勢:性能高了,線程安全了
 * 缺點:可讀性難度加大,不夠優雅
 */
public class LazyDoubleCheckSingleton {
    private volatile static LazyDoubleCheckSingleton instance;
    private LazyDoubleCheckSingleton(){}

    public static LazyDoubleCheckSingleton getInstance(){
        //檢查是否要阻塞
        if (instance == null) {
            synchronized (LazyDoubleCheckSingleton.class) {
                //檢查是否要從新建立實例
                if (instance == null) {
                    instance = new LazyDoubleCheckSingleton();
                    //指令重排序的問題
                }
            }
        }
        return instance;
    }
}

4.自認爲史上最牛的單例模式的實現方式 (這裏有個技術上的高深的點技術基礎點,說到底仍是技術的基礎和本質)----->>>> 利用了Java自己語法特色,內部類默認不加載線程

/*
  ClassPath : LazyStaticInnerClassSingleton.class
              LazyStaticInnerClassSingleton$LazyHolder.class
   優勢:寫法優雅,利用了Java自己語法特色,性能高,避免了內存浪費,不能被反射破壞
   缺點:不優雅
 */
//這種形式兼顧餓漢式單例模式的內存浪費問題和synchronized的性能問題
//完美地屏蔽了這兩個缺點
//自認爲史上最牛的單例模式的實現方式
public class LazyStaticInnerClassSingleton {
    //使用LazyInnerClassGeneral的時候,默認會先初始化內部類
    //若是沒使用,則內部類是不加載的
    private LazyStaticInnerClassSingleton(){
        if(LazyHolder.INSTANCE != null){
            throw new RuntimeException("不容許建立多個實例");
        }
    }
    //每個關鍵字都不是多餘的,static是爲了使單例的空間共享,保證這個方法不會被重寫、重載
    private static LazyStaticInnerClassSingleton getInstance(){
        //在返回結果之前,必定會先加載內部類
        return LazyHolder.INSTANCE;
    }

    //利用了Java自己語法特色,內部類默認不加載
    private static class LazyHolder{
        private static final LazyStaticInnerClassSingleton INSTANCE = new LazyStaticInnerClassSingleton();
    }

}

5.枚舉法code

public enum EnumSingleton {
    INSTANCE;

    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance(){return INSTANCE;}
}

 6.序列化一個單列對象對象

import java.io.Serializable;

public class SeriableSingleton implements Serializable {


    //序列化
    //把內存中對象的狀態轉換爲字節碼的形式
    //把字節碼經過IO輸出流,寫到磁盤上
    //永久保存下來,持久化

    //反序列化
    //將持久化的字節碼內容,經過IO輸入流讀到內存中來
    //轉化成一個Java對象


    public  final static SeriableSingleton INSTANCE = new SeriableSingleton();
    private SeriableSingleton(){}

    public static SeriableSingleton getInstance(){
        return INSTANCE;
    }

    private Object readResolve(){ return INSTANCE;}

}

 

7.手動建立一個單列對象(根據類名來建立)

public class ContainerSingleton {

    private ContainerSingleton(){}

    private static Map<String,Object> ioc = new ConcurrentHashMap<String, Object>();

    public static Object getInstance(String className){
        Object instance = null;
        if(!ioc.containsKey(className)){
            try {
                instance = Class.forName(className).newInstance();
                ioc.put(className, instance);
            }catch (Exception e){
                e.printStackTrace();
            }
            return instance;
        }else{
            return ioc.get(className);
        }
    }
}

8.ThreadLocal設置單列

public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> threadLocaLInstance =
            new ThreadLocal<ThreadLocalSingleton>(){
                @Override
                protected ThreadLocalSingleton initialValue() {
                    return new ThreadLocalSingleton();
                }
            };

    private ThreadLocalSingleton(){}

    public static ThreadLocalSingleton getInstance(){
        return threadLocaLInstance.get();
    }
}
相關文章
相關標籤/搜索