亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中如何實現單例模式

發布時間:2021-06-12 19:07:45 來源:億速云 閱讀:193 作者:Leah 欄目:編程語言

這篇文章將為大家詳細講解有關Java中如何實現單例模式,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

單例模式的特點

  1. 一個類只允許產生一個實例化對象。

  2. 單例類構造方法私有化,不允許外部創建對象。

  3. 單例類向外提供靜態方法,調用方法返回內部創建的實例化對象。

 懶漢式(線程不安全)

其主要表現在單例類在外部需要創建實例化對象時再進行實例化,進而達到Lazy Loading 的效果。

通過靜態方法 getSingleton() 和private 權限構造方法為創建一個實例化對象提供唯一的途徑。

不足:未考慮到多線程的情況下可能會存在多個訪問者同時訪問,發生構造出多個對象的問題,所以在多線程下不可用這種方法。

/**
 * @author MrRoot
 * @since 2018-12-17
 * 懶漢式(線程不安全)
 */
public class Singleton {
  private static Singleton singleton;

  private Singleton(){

  }

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

懶漢式(線程安全,同步方法,不推薦使用)

針對懶漢式的線程不安全,自然會想到給 getSingleton() 進行 synchronized 加鎖來保證線程同步。

不足:效率低。大多數情況下這個鎖占用的額外資源都浪費了,每個線程在想獲得類的實例時候,執行 getSingleton() 方法都要進行同步。

/**
 * @author MrRoot
 * @since 2019-3-27
 * 懶漢式(線程安全,同步方法,不推薦使用)
 */
public class Singleton {
  private static Singleton singleton;

  private Singleton(){

  }

  public static synchronized Singleton singleton(){
    if (singleton == null){
      singleton = new Singleton();
    }
    return singleton;
  }

}

餓漢式(線程安全)

在進行類加載時完成實例化對象的過程就是餓漢式的形式。

避免了線程同步問題,在運行這個類的時候進行加載,之后直接訪問

不足:相比接下來的靜態內部類而言,這種方法比靜態內部類多了內存常駐,容易造成內存浪費,也未達到延遲加載的效果。

/**
 * @author MrRoot
 * @since 2019-3-27
 * 餓漢式(線程安全)
 */
public class Singleton{
  private static Singleton singleton = new Singleton();

  private Singleton(){

  }

  public static Singleton singleton(){
    return singleton;
  }
}

靜態內部類加載(線程安全)

靜態內部類不會在單例加載時加載,當調用 getSingleton() 方法時才會進行加載,達到類似懶漢式效果,并且也是線程安全的。

類的靜態屬性只會在第一次加載類時進行初始化,所以上面的方法JVM 幫助我們保證了線程的安全性,在類進行初始化時,其他線程無法進入。

/**
 * @author MrRoot
 * @since 2019-3-27
 * 靜態內部類加載(線程安全)
 */
public class Singleton{
  private static Singleton singleton;

  private static class SingletonInner{
    private static final Singleton instance = new Singleton();
  }

  public static Singleton getSingleton(){
    return SingletonInner.instance;
  }
}

枚舉(線程安全)

自由串行化;保證只有一個實例;線程安全。

Effective Java 作者所提倡的方法,近乎完美,在繼承場景下不適用。

/**
 * @author MrRoot
 * @since 2019-3-27
 * 枚舉(線程安全)
 */
enum Singleton{
  INSTANCE;

  public void method(){

  }
}

class Test{
  public static void main(String[] args) {
    Singleton.INSTANCE.method();
  }
}

懶漢式雙重校驗鎖法(通常線程安全,不可保證完全安全)

使用同步代碼塊避免了第二種方法的效率低的問題,但此方法并不能完全起到線程同步的作用,與上面第一種方法產生的問題相似,多線程訪問時可能產生多個對象。

/**
 * @author MrRoot
 * @since 2019-3-27
 * 懶漢式雙重校驗鎖法(通常線程安全,不可保證完全安全)
 */
class Singleton{
  private static Singleton singleton;

  private Singleton(){

  }

  public static Singleton singleton(){
    if (singleton == null){
      synchronized (Singleton.class){
        if (singleton == null){
          singleton = new Singleton();
        }
      }
    }
    return singleton;
  }
}

懶漢式雙重檢查終極版

與第六種方法不同的是,此方法給singleton 的聲明上加了關鍵字 volatile ,進而解決了低概率的線程不安全問題。

volatile 起到禁止指令重排的作用,在它賦值完成之前,就不會調用讀操作(singleton == null)。

/**
 * @author MrRoot
 * @since 2019-3-27
 * 懶漢式雙重檢查終極版(volatile)
 */
class Singleton{
  private static volatile Singleton singleton;

  private Singleton(){

  }

  public static Singleton singleton(){
    if (singleton == null){
      synchronized (Singleton.class){
        if (singleton == null){
          singleton = new Singleton();
        }
      }
    }
    return singleton;
  }
}

使用 ThreadLocal 實現(線程安全)

ThreadLocal 會為每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數據的訪問沖突。

對于多線程資源共享的問題,同步機制采用了“以時間換空間”的方式,而ThreadLocal 采用了“以空間換時間”的方式。前者僅提供一份變量,讓不同的線程排隊訪問,而后者為每一個線程都提供了一份變量,因此可以同時訪問而互不影響。

/**
 * @author MrRoot
 * @since 2019-3-27
 * 使用 ThreadLocal 實現(線程安全)
 */
class Singleton{
  private static final ThreadLocal<Singleton> singleton = new
      ThreadLocal<Singleton>(){
        @Override
        protected Singleton initialValue(){
          return new Singleton();
        }
      };

  private Singleton(){

  }

  public static Singleton getSingleton(){
    return singleton.get();
  }
}

使用CAS 鎖實現(線程安全)

/**
 * @author MrRoot
 * @since 2019-3-27
 * 使用 CAS 實現(線程安全)
 */
public class Singleton {
  private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();

  private Singleton(){

  }

  public static final Singleton getSingleton(){
    for (;;){
      Singleton current = INSTANCE.get();
      if (current != null){
        return current;
      }
      current = new Singleton();
      if (INSTANCE.compareAndSet(null,current)){
        return current;
      }
    }
  }

  public static void main(String[] args) {
    Singleton singleton1 = Singleton.getSingleton();
    Singleton singleton2 = Singleton.getSingleton();
    System.out.println(singleton1 == singleton2);
  }
}

關于Java中如何實現單例模式就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阳春市| 镶黄旗| 舒城县| 蒲江县| 江油市| 三明市| 文化| 麟游县| 海口市| 垣曲县| 越西县| 宁晋县| 慈利县| 鄯善县| 拜泉县| 潮州市| 陇川县| 新竹市| 中阳县| 公主岭市| 郑州市| 余干县| 齐河县| 丰顺县| 沾化县| 东海县| 海伦市| 澎湖县| 吉隆县| 耒阳市| 依兰县| 堆龙德庆县| 涿鹿县| 屯昌县| 赤壁市| 阿拉尔市| 荣昌县| 河西区| 清丰县| 黄陵县| 陈巴尔虎旗|