單例模式總結

單例模式的含義java

單例模式的意思就是隻有一個實例。單例模式確保某一個類只有一個實例,並且自行實例化並向整個系統提供這個實例安全

通常只有一個私有的構造方法,它能夠經過調用公共的靜態方法來得到這個實例多線程

單例模式的好處併發

主要做用是保證在Java應用程序中,一個類Class只有一個實例存在。性能

使用Singleton的好處還在於能夠節省內存,由於它限制了實例的個數,有利於Java垃圾回收this

單例模式特色spa

一、單例類只能有一個實例。線程

二、單例類必須本身建立本身的惟一實例。code

三、單例類必須給全部其餘對象提供這一實例。對象

 

單例模式的選型:

 在實現層面上,目前的幾種主要的單例模式每每有如下幾項性能指標做爲選型參考:

  -- 是否實現延遲加載

  -- 是否線程安全

  -- 併發訪問性能

  -- 是否能夠防止反射與反序列化穿透

一個線程訪問一個對象中的synchronized(this)同步代碼塊時,其餘試圖訪問該對象的線程將被阻塞。

1.懶漢式單例

在類加載的時候不建立單例實例。只有在第一次請求實例的時候的時候建立,而且只在第一次建立後,之後再也不建立該類的實例。
懶漢式若是在建立實例對象時不加上synchronized則會致使對對象的訪問不是線程安全的

//單例模式-懶漢式單例
public class LazySingleton {
     //私有靜態對象,加載時候不作初始化
     private static LazySingleton m_intance=null;
     // 私有構造方法,避免外部建立實例
     private LazySingleton(){}
     /**
      * 靜態工廠方法,返回此類的惟一實例. 
      * 當發現實例沒有初始化的時候,才初始化.
      */
     synchronized public static LazySingleton getInstance(){
         if(m_intance==null){
             m_intance=new LazySingleton();
         }
         return m_intance;
     }
}

 

2. 餓漢式單例  

 在類加載的時候就建立實例,,在類建立的同時就已經建立好一個靜態的對象供系統使用

/*
* 單例模式-餓漢式單例
*/
public class EagerSingleton {
     /*
      * 私有的(private)惟一(static final)實例成員,在類加載的時候就建立好了單例對象
      */
     private static final EagerSingleton m_instance = new EagerSingleton();

     /**
      * 私有構造方法,避免外部建立實例
      */
     private EagerSingleton() {
     }

     /**
      * 靜態工廠方法,返回此類的惟一實例.
      * @return EagerSingleton
      */
     public static EagerSingleton getInstance() {
         return m_instance;
     }
}

3. 登記式單例

這個單例實際上維護的是一組單例類的實例,將這些實例存放在一個HashTable(登記薄)中,對於已經登記過的實例,則從工廠直接返回,對於沒有登記的,則先登記,然後返回。 

//用來存儲單例(StringManager)的變量的hash類
private static HashTable managers = new HashTable();
//下面用關鍵字synchronized避免多線程時出錯。
public synchronized static StringManager getManager(String packageName){
    StringManager mgr = (StringManager)managers.get(packageName);
    if(mgr == null){
        mgr = new StringManager(packageName);
        managers.put(packageName,mgr);
   }
return mgr;
}

4.雙重鎖定單例(改進懶漢式)

考慮這樣一種狀況,就是有兩個線程同時到達,即同時調用 getInstance() 方法。兩個線程都會建立一個實例,這就違背了單例模式的初衷。所以加雙重鎖定

public class Singleton {  
    private static volatile Singleton instance;  
  
    private Singleton() {  
    }  
  
    public static Singleton getInstance() {  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                if (instance == null) {  
                    instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }  
}

  

啊啊

相關文章
相關標籤/搜索