java中9種常見的單例模式

單例模式分爲兩大種,一種是餓漢模式,一種是懶漢模式(懶加載)

餓漢模式

1.單例-餓漢模式 佔用內存常駐,靜態常量直接初始化

public class Singleton01 {
    //單例-餓漢模式  佔用內存常駐
    private Singleton01() {
        if(SINGLETON!=null){
            throw new RuntimeException();
        }
    }

    private static final Singleton01 SINGLETON = new Singleton01();

    public Singleton01 getInstance() {
        return SINGLETON;
    }

}

 

2.單例-餓漢模式 不佔用內存常駐,採用靜態內部類直接初始化

public class Singleton02 {
    //單例-餓漢模式  不佔用內存常駐
    private static class Singleton02Inner {
        private static final Singleton02 SINGLETON = new Singleton02();
    }

    private Singleton02() {
        if (Singleton02Inner.SINGLETON != null) {
            throw new RuntimeException();
        }
    }

    public Singleton02 getInstance() {
        return Singleton02Inner.SINGLETON;
    }

3.採用枚舉類型

public enum Singleton03 {
    //枚舉實例
    SINGLETON;

    public void otherMethod() {

    }

}

 

懶漢模式(懶加載)

4.單例-懶漢模式 實現懶加載,線程不安全,多線程時,不一定只有一個實例

public class Singleton04 {
    //單例-懶漢模式 實現懶加載,線程不安全
    private static Singleton04 singleton = null;

    private Singleton04() {
        if (singleton != null) {
            throw new RuntimeException();
        }
    }

    public static Singleton04 getInstance() {
        if (singleton == null) {
            singleton = new Singleton04();
        }
        return singleton;
    }

    public static void main(String[] args) {
        System.out.println(getInstance() == getInstance());
    }

}

 

5.單例-懶漢模式 線程安全寫法,但是效率不高,開銷大

public class Singleton05 {
    //單例-懶漢模式   線程安全寫法,但是效率不高,開銷大
    private static Singleton05 singleton = null;

    private Singleton05() {
        if (singleton != null) {
            throw new RuntimeException();
        }
    }

    public static synchronized Singleton05 getInstance() {
        if (singleton == null) {
            singleton = new Singleton05();
        }
        return singleton;
    }

    public static void main(String[] args) {
        System.out.println(getInstance() == getInstance());
    }
}

 

6.單例-懶漢模式 線程不完全安全寫法,效率比同步方法高,雙重校驗鎖

public class Singleton06 {
    //單例-懶漢模式   線程不完全安全寫法,效率比同步方法高,雙重校驗鎖
    private static Singleton06 singleton = null;

    private Singleton06() {
        if (singleton != null) {
            throw new RuntimeException();
        }
    }

    public static Singleton06 getInstance() {
        if (singleton == null) {
            synchronized (Singleton06.class) {
                if (singleton == null) {
                    singleton = new Singleton06();
                }
            }
        }
        return singleton;
    }

}

 

7.單例-懶漢模式 線程安全寫法,效率比同步方法高,雙重校驗鎖升級版

public class Singleton07 {
    //單例-懶漢模式   線程安全寫法,效率比同步方法高,雙重校驗鎖升級版
    //volatile 起到禁止指令重排的作用,在它賦值完成之前,就不會調用讀操作(singleton == null)。
    private static volatile Singleton07 singleton = null;

    private Singleton07() {
        if (singleton != null) {
            throw new RuntimeException();
        }
    }

    public static Singleton07 getInstance() {
        if (singleton == null) {
            synchronized (Singleton07.class) {
                if (singleton == null) {
                    singleton = new Singleton07();
                }
            }
        }
        return singleton;
    }
}

8.使用 ThreadLocal 實現(線程安全)

public class Singleton08 {
    //使用 ThreadLocal 實現(線程安全)
    //ThreadLocal 會爲每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數據的訪問衝突。
    //對於多線程資源共享的問題,
    // 同步機制採用了“以時間換空間”的方式,而ThreadLocal 採用了“以空間換時間”的方式。
    // 前者僅提供一份變量,讓不同的線程排隊訪問,而後者爲每一個線程都提供了一份變量,
    // 因此可以同時訪問而互不影響。
    private static final ThreadLocal<Singleton08> SINGLETON = new ThreadLocal<Singleton08>() {
        @Override
        protected Singleton08 initialValue() {
            return new Singleton08();
        }
    };

    private Singleton08() {

    }

    public static Singleton08 getInstance() {
        return SINGLETON.get();
    }
}

9.CAS鎖實現,比較再交換(線程安全)

public class Singleton09 {
    //CAS鎖實現,比較再交換
    private static final AtomicReference<Singleton09> SINGLETON = new AtomicReference<>();

    private Singleton09() {

    }

    public static final Singleton09 getInstance() {
        for (; ; ) {
            Singleton09 current = SINGLETON.get();
            if (current != null) {
                return current;
            }
            current = new Singleton09();
            if (SINGLETON.compareAndSet(null, current)) {
                return current;
            }
        }
    }

    public static class MyTest {
        @Test
        public void test() throws InterruptedException {
          Thread th =   new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        for (int i = 0; i < 100000; i++) {
                            long i1 =  i ^ 5;
                            System.out.println(i1);
                        }
                        System.out.println("aaaa");
                        notifyAll();
                        Thread.currentThread().sleep(10000);

                        System.out.println("fdsafsa");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
          th.start();
          th.join();
          System.out.println("woshitest");

        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章