1. 程式人生 > >執行緒安全單例設計模式+序列化

執行緒安全單例設計模式+序列化

懶漢式單例模式會引來執行緒安全問題,即多執行緒時可能會建立多個例項,而且在反序列化時也可能會建立新的例項。看了大大們的實現方式,覺得以下一種比較簡單方便理解。


一、下面是會造成執行緒安全的餓漢單例模式。用四列印下會發現hashcode不一致

public class Singleton {  
      
    private static Singleton instance = null;  
    //禁止new
    private Singleton(){}  
      
    public static Singleton getInstance() {  
        if(instance == null){//懶漢式   
            instance = new MySingleton();
        }
        return instance;  
    }  
}  


二、靜態程式碼塊中的程式碼在使用類的時候就已經執行了,所以可以應用靜態程式碼塊的這個特性實現單例設計模式。

public class Singleton implements Serializable{
    private static final long serialVersionUID = 1L;
    private static Singleton instance = null;//餓漢式

    //靜態程式碼塊實現單例模式執行緒安全
    static {
        instance = new Singleton();
    }

    public static Singleton getSingleton() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    //該方法在反序列化時會被呼叫
    protected Object readResolve() throws ObjectStreamException {
        System.out.println("呼叫了readResolve方法!");
        return Singleton.instance;
    }
}

三、多執行緒呼叫列印例項的hashCode
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Singleton.getSingleton().hashCode());
        }
    }

    public static void main(String[] args) throws Exception {
        MyThread[] mts = new MyThread[3];
        for (int i = 0; i < mts.length; i++) {
            mts[i] = new MyThread();
        }

        for (int j = 0; j < mts.length; j++) {
            mts[j].start();
        }
    }
}

四、列印序列化和反序列後例項的hashcode

/**
 * java類簡單作用描述
 *
 * @Author: Sosmmh
 * @CreateDate: 2018/2/27 10:56
 **/
public class SaveAndReadForSingleton {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getSingleton();

        File file = new File("MySingleton.txt");

        try {
            FileOutputStream fos = new FileOutputStream(file);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(singleton);
            fos.close();
            oos.close();
            System.out.println(singleton.hashCode());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            FileInputStream fis = new FileInputStream(file);
            ObjectInputStream ois = new ObjectInputStream(fis);
            Singleton rSingleton = (Singleton) ois.readObject();
            fis.close();
            ois.close();
            System.out.println(rSingleton.hashCode());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }
}
詳細介紹請看原文大大。 詳細介紹單例模式