05.并發(fā)編程之單例和多線程

1、ThreadLocal

線程局部變量,是一種多線程間并發(fā)訪問變量的解決方案,與synchronized加鎖方式不同,ThreadLocal完全不提供鎖,而使用以空間換時間的手段,為每個線程提供變量的獨立副本,保障線程安全。
從性能上講, ThreadLocal不具有絕對的優(yōu)勢,在并發(fā)不是很高的時候,加鎖性能會更好,但在高并發(fā)或者競爭激烈時,如硬件較好,用ThreadLocal一定程度上減少鎖競爭。

2、單例模式

單例模式的饑餓與懶漢模式在多線程中是不行的,性能不高且不能保證線程安全
靜態(tài)內(nèi)部類模式,推薦,最安全,最可靠

    public class InnerSingleton {
        private static class Singleton {
            private static Singleton single = new Singleton();
        }
        public static Singleton getInstance() {
            return Singleton.single;
        }
    }
    比較:
    package demo2;

    public class MySingleTon {

        // 1:餓漢 一旦完成加載,就把單例初始化完成,getInstance時已存在

        private final static MySingleTon singleTon = new MySingleTon();

        private MySingleTon() {
            System.out.println("starting init single");
        }

        public static MySingleTon getInstance() {
            return singleTon;
        }

        public static void main(String[] args) {
            System.out.println("-------------");
            MySingleTon sinle1 = MySingleTon.getInstance();
            System.out.println("-------------");
            MySingleTon sinle2 = MySingleTon.getInstance();
            System.out.println("-------------");
            MySingleTon sinle3 = MySingleTon.getInstance();
        }
    }
    打?。?    starting init single
    -------------
    -------------
    -------------
    
    package demo2;

    public class MySingleTon {

        // 2 線程安全的 懶漢式 調(diào)用getInstance時 初始化實例

        private static MySingleTon single = null;

        private MySingleTon() {
            System.out.println("starting init single");
        }

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

        public static void main(String[] args) {
            System.out.println("-------------");
            MySingleTon sinle1 = MySingleTon.getInstance();
            System.out.println("-------------");
            MySingleTon sinle2 = MySingleTon.getInstance();
            System.out.println("-------------");
            MySingleTon sinle3 = MySingleTon.getInstance();
        }
    }
    打印
    -------------
    starting init single
    -------------
    -------------
    public class Singleton  
    {  
        private Singleton(){ }  
        
        public static Singleton getInstance()  
        {  
            return Nested.instance;       
        }  
        
        //在第一次被引用時被加載  
        static class Nested  
        {  
            private static Singleton instance = new Singleton();  
        }  
        
        public static void main(String args[])  
        {  
            Singleton instance = Singleton.getInstance();  
            Singleton instance2 = Singleton.getInstance();  
            System.out.println(instance == instance2);  
        }  
    }  

3、至于1、2、3這三種實現(xiàn)又有些區(qū)別:

  • 第1種:餓漢式在類創(chuàng)建的同時就實例化一個靜態(tài)對象出來,不管之后會不會使用這個單例,都會占據(jù)一定的內(nèi)存,但是相應的,在第一次調(diào)用時速度也會更快,因為其資源已經(jīng)初始化完成,
  • 第2種,在getInstance中做了兩次null檢查,確保了只有第一次調(diào)用單例的時候才會做同步,這樣也是線程安全的,同時避免了每次都同步的性能損耗
  • 第3種,利用了classloader的機制來保證初始化instance時只有一個線程,所以也是線程安全的,同時沒有性能損耗,所以一般我傾向于使用這一種。
PS1

一種通過內(nèi)部類來實現(xiàn)單例的方式,靜態(tài)內(nèi)部類只能訪問外部類的靜態(tài)方法和靜態(tài)屬性?,F(xiàn)在一般利用這個特性來實現(xiàn)單例模式。因為類在初始化的時候線程是互斥的,可以完美的解決單例創(chuàng)建沖突的問題。

PS2

單例模式是一種常見的模式,懶漢模式考慮線程安全需要在獲取單例的方法添加synchronized關鍵字實現(xiàn)同步代碼塊,這樣造成了性能損耗;而餓漢模式不能延遲實例化對象,靜態(tài)內(nèi)部類單例模式的實現(xiàn),既保證了線程的安全,有能夠延遲加載,也就是在第一次使用的時候加載。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 單例模式(SingletonPattern)一般被認為是最簡單、最易理解的設計模式,也因為它的簡潔易懂,是項目中最...
    成熱了閱讀 4,530評論 4 34
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,913評論 25 709
  • 一天一天的時間好快,2017年上半年就這樣悄悄過去了。想要做的事情做到了嗎? 上次去參加qiqi的無保留分享會,最...
    D025Alicia深圳閱讀 151評論 0 0
  • 第二十四天打卡 繪制流程很簡單,大家都可以畫畫哦! 叫上好朋友一起畫吧!(?????)
    趙縵纓閱讀 1,694評論 4 8
  • 現(xiàn)代社會其實是一個灑雞湯的社會,每個人都在灑雞湯,看誰灑的好,灑的多,灑的漂亮、如果你就一件事詢問別人的意見,你會...
    科恩先生閱讀 400評論 0 0

友情鏈接更多精彩內(nèi)容