java單例模式各種實現方式

Java中單例模式是一種經常用到的模式,並且在面試中是經常出現的,那麼我們今天就看看各種實現方式。

  • 單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。
  1. 餓漢模式
public class Singleton{
    private static Singleton singleton = new Singleton();
    private Singleton(){};
    public static Singleton() getInstance(){
        return singleton;
    }
}
  • 優點 : 類加載的時候就創建一次,並且是線程安全的。
  • 缺點 : 即使這個類沒有被用到也會被創建,所以內存會被浪費。
  1. 懶漢模式
  public class Singleton{
      private static Singleton singleton = null;
      private Singleton (){};
      public static Singleton getInstance(){
          if (singleton == null) {
              singleton = new Singleton();
          }
          return singleton;
      }
  }
  • 優點: 在需要的時候纔會被創建。
  • 缺點: 線程不安全。於是我們加上線程鎖
  public class Singleton{
      private static Singleton singleton = null;
      private Singleton (){};
      public static synchronized Singleton getInstance(){
          if (singleton == null) {
              singleton = new Singleton();
          }
          return singleton;
      }
  }
  • 優點: 解決了線程安全問題。
  • 缺點: 線程鎖寫在方法上這樣性能會很差,因爲在每次調用方法的時候都會進行鎖操作。
  1. 雙重校驗鎖(推薦)
   public class Singleton{
      private static Singleton singleton = null ;
      private Singleton (){};
      public statice Singleton getInstance(){
          if(singleton == null) { // 第一次檢查
               synchronized (Singleton.class) {
                   if(singleton == null) { // 第二次檢查
                       singleton = new Singleton();
                   }
               }
           }
           return singleton;
      }
   }
  • 優點: 線程安全,並且是延時加載,有兩次判斷會提高執行效率。
  • 缺點: 存在雙檢鎖隱患。
  • 什麼是雙檢鎖隱患?
    • 簡單了的說由於java虛擬機裏存在指令重排,所謂指令重排優化是隻在不改變元語句含義的同時調整指令的 執行順序讓程序執行的更快。就是由於指令重排的存在就會導致初始化Singleton將對象的內存地址賦值給singleton字段的順序是不確定的。
  • 但是在jdk1.5之後java推出了volatile 關鍵字(如果對volatile關鍵字感興趣可以出門google一下),此關鍵字會解決指令重排。於是會解決雙檢鎖隱患。
   public class Singleton{
      // 使用volatile 關鍵字防止指令重排
      private static volatile Singleton singleton = null ;
      private Singleton (){};
      public statice Singleton getInstance(){
          if(singleton == null) { // 第一次檢查
               synchronized (Singleton.class) {
                   if(singleton == null) { // 第二次檢查
                       singleton = new Singleton();
                   }
               }
           }
           return singleton;
      }
   }
  1. 靜態內部類(推薦)
  public class Singleton{
      private static class SingletonHolder {
          public static Singleton singleton = new Singleton();
      }
      private Singleton(){};
      public static Singleton getInstance(){
          teturn SingletonHolder.singleton;
      }
  }
  • 優點: 同樣使用了類加載器的方式創建了對象,與餓漢式一樣,同時保證了延時加載和線程安全。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章