Java設計模式-單例模式

Java設計模式之單例模式

單例模式(Singleton Pattern)是一個比較簡單的設計模式,主要是爲了保證在系統運行過程中,程序只能提供一個對應該類的實例

1. 單例模式的實現

1.1單例模式的通用UML圖

單例模式通用UML圖

1.2 餓漢模式

所謂“餓漢模式”就是無論程序是否需要調用這個實例,JVM在類加載過程之後就會創建這樣一個實例。

    //餓漢模式
    public class Singleton{
        private static Singleton singleton = new Singleton();
        //使用私有構造函數,可以限制開發者通過new方法創建多個對象
        private Singleton(){
            //創建實例的操作,一般比較耗時
        }

        public static Singleton getInstance(){
            return singleton;
        }
    }

1.3 懶漢模式

“懶漢模式”就是當程序需要這個實例的時候,才創建這個實例,以後再出現使用該實例的情況,就會直接獲取到已經創建好的實例對象。

    //懶漢模式
    public class Singleton{
        //初始爲null,在需要調用時創建實例
        private static Singleton singleton = null;

        private Singleton(){
            //創建實例的操作,一般比較耗時
        }

        public static Singleton getInstance(){
            //如果singleton爲null,就執行構造函數
            if(singleton == null){
                singleton = new Singleton();
            }
            return singleton;
        }
    }

2 線程安全的單例模式

2.1 線程安全性討論

一般情況下,懶漢模式由於只有在第一次需要調用實例的時候纔會創建實例,這樣就節省了整個程序的加載時間,相比於惡漢模式具有一定的優勢。但是懶漢模式的實現方式在高併發情況下並不是安全的。
在singleton沒有被初始化之前,如果有多個線程同時去嘗試獲取這個實例,但程序執行到if(singleton==null)時,會有多個線程同時進入到if判斷的內部,從而創建多個singleton實例,這樣就破壞了線程安全性。
爲了保證單例模式的線程安全,因此我們在創建單例的時候對共享資源進行隔離。

2.2 使用synchronized關鍵字實現線程安全

1. 使用同步方法

    //線程安全的懶漢模式
    public class Singleton{
        //初始爲null,在需要調用時創建實例
        private static Singleton singleton = null;

        private Singleton(){
            //創建實例的操作,一般比較耗時
        }

        public static synchronized Singleton getInstance(){
            //如果singleton爲null,就執行構造函數
            if(singleton == null){
                singleton = new Singleton();
            }
            return singleton;
        }
    }

2. 使用同步代碼塊

    //線程安全的懶漢模式
    public class Singleton{
        //初始爲null,在需要調用時創建實例
        private static volatile Singleton singleton = null;

        private Singleton(){
            //創建實例的操作,一般比較耗時
        }

        public static Singleton getInstance(){
            //如果singleton爲null,就執行構造函數
            if(singleton == null){
                //使用synchronized關鍵字給以下代碼加入類鎖
                synchronized(Singleton.class){
                    if (singleton == null){
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }

3. 使用靜態內部類

    //線程安全的單例模式
    public class Singleton(){
        //靜態內部類
        private static class InnerSingleton{
            private static Singleton singleton = new Singleton();
        }

        private Singleton(){
            //初始化操作
        }

        public static Singleton getInstance(){
            return InnerSingleton.singleton;
        }
    }

靜態內部類實現單例模式的原理是靜態內部類在類加載過程中就已經被初始化,且整個生命週期中只會被初始化一次。因此可以保證靜態內部類裏面的對象是一個單例。

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