設計模式 單例模式

干饭达人GoodLucy發表於2024-07-31

雙重檢查鎖

package com.fh.design_mode.singleton.double_check_lock;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

/**
 * 雙重檢查鎖
 */
public class SingletonTest {

    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "例物件=" + Singleton.getInstance());
            }, "執行緒" + i).start();
        }
    }
}

class Singleton {
    private static volatile Singleton instance = null;//volatile 禁止重排序

    private Singleton() {
    }

    @SneakyThrows
    public static Singleton getInstance() {
        if (instance == null) {//效率
            synchronized (Singleton.class) {
                System.out.println("【debug】" + Thread.currentThread().getName() + "獲得物件鎖");
                TimeUnit.SECONDS.sleep(2);
                if (instance == null) {//物件是否為空
                    /*
                    ①分配棧空間=》②分配堆記憶體=》③棧指標指向堆記憶體
                    因為重排序最佳化的存在
                    執行緒A①③棧指標指向堆記憶體,例項分配記憶體後就不是null。
                    執行緒B進入判斷instance!=null,直接返回A執行緒建立的不完整的例項。
                    */
                    instance = new Singleton();
                }
                System.out.println("【debug】" + Thread.currentThread().getName() + "釋放物件鎖。。。");
            }
        }
        return instance;
    }
}

靜態內部類

package com.fh.design_mode.singleton.static_inner_class;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

/**
 * 靜態內部類
 */
public class SingletonTest {

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                Singleton.SingletonHolder a = new Singleton.SingletonHolder();

                System.out.println(Singleton.getInstance());
            }).start();
        }
    }
}

class Singleton {

    private Singleton() {

    }

    static class SingletonHolder {
        //虛擬機器會保證一個類的 <clinit>() 方法在多執行緒環境中能被正確的加鎖、同步。
        private static Singleton INSTANCE = new Singleton();
    }

    @SneakyThrows
    public static Singleton getInstance() {
        TimeUnit.SECONDS.sleep(3);
        return SingletonHolder.INSTANCE;
    }
}

餓漢式

package com.fh.design_mode.singleton.hungry_lock;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

/*
 *餓漢式
 * */
public class SingletonTest {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.out.println(Sinleton.getInstance());
            }).start();
        }
    }
}

class Sinleton {

    private static final Sinleton instance = new Sinleton();

    private Sinleton() {
    }

    @SneakyThrows
    public static Sinleton getInstance() {
        TimeUnit.SECONDS.sleep(2);
        return instance;
    }
}

相關文章