天天看點

Java多線程程式設計核心技術--第六章

Chapter 6

第六章主要介紹如何使單例模式遇到多線程是安全的、正确的

  • 立即加載/”餓漢式”
/**
 * 立即加載單例模式/”餓漢式“
 * Created by boboan on 2018/6/5.
 */
public class MyObject {
    private static MyObject myObject = new MyObject();

    public MyObject() {
    }
    public static MyObject getInstance(){
        return myObject;
    }
}
           
  • 延遲加載/”懶漢式”
/**
 * 延遲加載單例模式/"懶漢式"
 * 
 * Created by boboan on 2018/6/5.
 */
public class MyObject2 {
    private static MyObject2 myObject;

    public MyObject2() {
    }
    public static MyObject2 getInstance(){
        if (myObject != null) {

        }else {
            return myObject = new MyObject2();
        }
        return myObject;
    }
}
           

但是這種方法在多線程的情況是錯誤的,出現多例的情況

/**
 * 延遲加載單例模式/"懶漢式"
 * 
 * Created by boboan on 2018/6/5.
 */
public class MyObject3 {
    private static MyObject3 myObject;

    public MyObject3() {
    }
    //設定同步方法效率比較低
    //給方法加鎖
    synchronized public static MyObject3 getInstance(){
        try {
            if (myObject != null) {

            }else {
                Thread.sleep();
                return myObject = new MyObject3();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }
}
           

這種方法在多線程是錯誤的,可以通過加 synchronized 同步來解決

/**
 * 延遲加載單例模式/"懶漢式"
 * 
 * Created by boboan on 2018/6/5.
 */
public class MyObject4 {
    private static MyObject4 myObject;

    public MyObject4() {
    }

    public static MyObject4 getInstance(){
        try {

                if (myObject != null) {

                }else {
                    synchronized (MyObject4.class) {
                        Thread.sleep();
                        return myObject = new MyObject4();
                    }
                }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }
}
           

synchronized 同步效率低,采用同步代碼塊,對關鍵代碼同步效率稍微提升,但是多線程下還是無法解決

  • DCL 雙檢查鎖機制(推薦)
/**
 * 延遲加載單例模式/"懶漢式"
 * 
 * Created by boboan on 2018/6/5.
 */
public class MyObject5 {
    private volatile static MyObject5 myObject;

    public MyObject5() {
    }

    public static MyObject5 getInstance(){
        try {

                if (myObject != null) {

                }else {
                        Thread.sleep();
                        synchronized (MyObject5.class) {
                            if (myObject==null) {
                                myObject = new MyObject5();
                            }
                        }
                }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return myObject;
    }
}
           

DCL 雙檢查鎖機制來解決問題,保證了不需要同步代碼塊的異步執行,又保證了單例的效果

  • 靜态内置類實作單例模式(推薦)
/**
 * 靜态内置類實作單例模式
 *
 * Created by boboan on 2018/6/5.
 */
public class MyObject6 {
    private static class MyObjectHandler{
        private static MyObject myObject = new MyObject();
    }

    public MyObject6() {
    }

    public static MyObject getInstance(){
        return MyObjectHandler.myObject;
    }
}
           
  • 序列化與反序列化實作單例模式
**
 * 序列化與反序列化實作單例模式
 * 避免枚舉類暴露
 *
 * Created by boboan on //
 */
public class MyObject10 implements Serializable{
    public static  final  long seriVersionUID = L;
    public static class MyObjectHandler{
        private static final MyObject10 myObject10= null;
    }
    private  MyObject10(){

    }
    public  static MyObject10 getInstance(){
        return MyObjectHandler.myObject10;
    }
    protected Object readResolve(){
        System.out.println("調用了 read 方法");
        return MyObjectHandler.myObject10;
    }
}
           
  • static 代碼塊實作單例模式
/**
 * static 代碼塊實作單例模式
 *
 * Created by boboan on 2018/6/5.
 */
public class MyObject7 {
    private static MyObject myObject = null;

    public MyObject7() {
    }

    static {
        myObject = new MyObject();
    }
    public static MyObject getInstance(){
        return myObject;
    }
}
           

靜态代碼塊在使用類的時候就執行了,利用此特性實作單例

  • enum 枚舉資料類型實作單例模式
/**
 * 枚舉類實作單例模式
 * 避免枚舉類暴露
 *
 * Created by boboan on 2018/6/5.
 */
public class MyObject9 {
    public enum MyenumSingleton{

    connectionFactory;
    private  int tag;
    private MyenumSingleton() {
        System.out.println("調用了");
        tag = ;
    }
    public int getTag(){
        return tag;
    }
    }
    public static int getComTag(){
        return MyenumSingleton.connectionFactory.getTag();
    }

}
           

使用枚舉類時,構造方法會被自動調用。是以可以用來建立單例

繼續閱讀