Java安全的發佈對象

安全發佈對象

  • 在靜態初始化函數中初始化一個對象引用
  • 將對象的引用保存到volatile類型域或者AtomicReference對象中
  • 將對象的引用保存到某個正確構造對象的final類型域中
  • 將對象的引用保存到一個由鎖保護的域中
Spring 框架中,Spring管理的類都是單例模式。如何保證一個實例只被初始化一次,且線程安全?經過不一樣單例的寫法,具體描述安全發佈對象的四種方法:

在靜態初始化函數中初始化一個對象的引用(不推薦)

package com.rumenz.task.single;


//線程安全
//餓漢模式
//靜態代碼塊初始化
public class SingletonExample {
    private SingletonExample(){
        //初始化操做
    }
    private static SingletonExample singletonExample=null;

    static {
        singletonExample=new SingletonExample();
    }

    public static SingletonExample getInstance(){
        return singletonExample;
    }
}

//或者
package com.rumenz.task.single;
//線程安全
//餓漢模式
//靜態代碼塊初始化
public class SingletonExample {
    private SingletonExample(){

        //初始化操做

    }
    private static SingletonExample singletonExample=new SingletonExample();



    public static SingletonExample getInstance(){
        return singletonExample;
    }
}
缺點:用不用都會初始化對象,若是初始化工做較多,加載速度會變慢,影響系統性能。

將對象的引用保存到volatile類型或AtomicReference對象中(推薦)

package com.rumenz.task.single;

//線程安全
//懶漢模式
public class SingletonExample1 {

    private SingletonExample1() {
        //初始化操做
    }
    // 一、memory = allocate() 分配對象的內存空間
    // 二、ctorInstance() 初始化對象
    // 三、instance = memory 設置instance指向剛分配的內存
    // 單例對象 volatile + 雙重檢測機制 -> 禁止指令重排
    private volatile static SingletonExample1 singletonExample1=null;
    //靜態工廠方法
    public static SingletonExample1 getInstance(){
        if(singletonExample1==null){ //雙重檢測
            synchronized(SingletonExample1.class){ //同步鎖
                if(singletonExample1==null){
                    singletonExample1=new SingletonExample1();
                }
            }
        }
        return singletonExample1;
    }
}
優勢:按需加載
缺點:第一次初始化的時候可能會比較慢

經過synchronized(不推薦)

package com.rumenz.task.single;

public class SingletonExample3 {
    //私有構造函數
    private SingletonExample3(){
        //初始化操做
    }

    private static SingletonExample3 singletonExample3=null;
    //靜態的工廠方法
    public static synchronized SingletonExample3 getSingletonExample3(){
         if(singletonExample3==null){
             singletonExample3=new SingletonExample3();
         }
         return singletonExample3;
    }
}
缺點:每次進入 getSingletonExample3都會加鎖,耗費資源,故不推薦使用。

枚舉(推薦)

package com.rumenz.task.single;

public class SingletonExample4 {

    //私有構造函數
    private SingletonExample4(){
       //初始化
    }
    public static SingletonExample4 getSingletonExample4(){
        return Singleton.INSTANCE.getSingleton();
    }
    private enum Singleton{
        INSTANCE;
        private SingletonExample4 singleton;
        Singleton(){
            singleton=new SingletonExample4();
        }
        public SingletonExample4 getSingleton(){
            return singleton;
        }

    }
}
優勢:自然線程安全,可防止反射生成實例,推薦使用

相關文章
相關標籤/搜索