一、單例模式

文章目錄

  • 1 基本介紹
  • 2 實現方式
    • 2.1 餓漢式
      • 2.1.1 代碼
      • 2.1.2 特性
    • 2.2 懶漢式 ( 線程不安全 )
      • 2.2.1 代碼
      • 2.2.2 特性
    • 2.3 懶漢式 ( 線程安全 )
      • 2.3.1 代碼
      • 2.3.2 特性
    • 2.4 雙重檢查
      • 2.4.1 代碼
      • 2.4.2 特性
    • 2.5 靜態內部類
      • 2.5.1 代碼
      • 2.5.2 特性
    • 2.6 枚舉
      • 2.6.1 代碼
      • 2.6.2 特性
  • 3 實現的要點
  • 4 線程不安全的單例模式
    • 4.1 代碼
    • 4.2 評價
  • 5 JDK中的單例模式
  • 6 單例模式的類圖及角色
    • 6.1 類圖
    • 6.2 角色
  • 7 推薦的單例模式的實現
  • 8 單例模式的使用場景

1 基本介紹

單例模式(Singleton Pattern)是一種常用的軟件設計模式,其目的是 確保一個類僅有一個實例,并提供一個 靜態方法 來獲取該實例。

2 實現方式

單例模式圍繞著兩個特性展開:

  • 延遲加載:在需要這個單例時才創建單例,避免浪費內存。
  • 線程安全:在多線程環境下,保證多線程使用的單例是同一個單例。

共有以下六種實現方式:

2.1 餓漢式

2.1.1 代碼

餓漢式的實現在 Java 中有兩種實現,常用的是第一種。

方式一:給靜態常量賦初始值

public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {}public static synchronized Singleton getInstance() {return INSTANCE;}
}

方式二:使用靜態代碼塊賦值

public class Singleton {private static final Singleton INSTANCE;static {INSTANCE = new Singleton();}private Singleton() {}public static synchronized Singleton getInstance() {return INSTANCE;}
}

2.1.2 特性

  • 不延遲加載:在 類加載 時就創建單例。
  • 線程安全類加載由 JVM 保證線程安全,所以此時創建的單例也是線程安全的。

2.2 懶漢式 ( 線程不安全 )

2.2.1 代碼

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

2.2.2 特性

  • 延遲加載:只有在 調用獲取單例的方法 getInstance() 時才創建單例。
  • 線程不安全:如果有多個線程同時通過了 if (singleton == null) 這個條件,則它們會創建多個單例。

2.3 懶漢式 ( 線程安全 )

2.3.1 代碼

注意 getInstance() 方法前的 synchronized 修飾符。

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

2.3.2 特性

  • 延遲加載:只有在 調用獲取單例的方法 getInstance() 時才創建單例。
  • 線程安全:在多個線程同時獲取單例時,使用 synchronized 互斥鎖,來保證只有一個線程能夠生成單例,而其他線程等待這個線程創建的單例,保證了單例的線程安全。
  • 成本太大:即使已經有單例了,每次調用 getInstance() 方法還得經過 加鎖釋放鎖 的流程(因為使用了 synchronized 互斥鎖),降低了并發性能

2.4 雙重檢查

2.4.1 代碼

注意單例前的 volatile 修飾符,它有兩個作用:保證變量對所有線程可見防止指令重排。在此處起 防止指令重排 的作用:防止 JIT 即時編譯器對 instance = new Singleton(); 這行代碼進行重排序

如果進行重排序,則可能先給 instance 分配內存(此時 instance != null),然后才調用構造器為 instance 的屬性賦值。在這兩步操作之間,要是有線程調用 getInstance() 方法,它將無法通過外層的 instance == null 條件,會返回一個不完整(賦值不完全)的對象。

public class Singleton {private static volatile Singleton instance; // 注意 volatile 在這里起 防止指令重排 的作用private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}}

2.4.2 特性

  • 延遲加載:只有在 調用獲取單例的方法 getInstance() 時才創建單例。
  • 線程安全:在多個線程同時獲取單例 且 單例未創建時,如果都通過了外層的 instance == null 條件,則在內層使用 synchronized 互斥鎖,來保證只有一個線程創建單例,而其他線程等待這個線程創建的單例,保證了單例的線程安全。
  • 成本小:這種實現方式只有最初創建單例時會加互斥鎖,之后就不需要創建單例了,直接返回即可,無需加鎖和釋放鎖,提高了并發性能

2.5 靜態內部類

2.5.1 代碼

public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

2.5.2 特性

  • 延遲加載:只有在 調用獲取單例的方法 getInstance() 時,才會 觸發靜態內部類的加載,從而創建單例。
  • 線程安全:靜態內部類也是類,類加載由 JVM 保證其線程安全,所以本單例是線程安全的。

2.6 枚舉

2.6.1 代碼

public enum Singleton {INSTANCE; // 直接使用 Singleton.INSTANCE 就可以獲取到單例// 可以隨意寫方法和屬性,就像在類中一樣
}

2.6.2 特性

  • 不延遲加載:在 類加載 時就創建單例。
  • 線程安全類加載由 JVM 保證線程安全,所以此時創建的單例也是線程安全的。
  • 防止 反射 或 反序列化 破壞單例:其他單例的實現都可以通過 反射 或 反序列化 的方式重新創建新的單例,唯獨本實現無法使用這兩種方式重新創建新的單例,這是因為 枚舉無法通過反射獲取對象,并且 枚舉在序列化和反序列化時不會調用構造器。所以這種實現是 最推薦的

3 實現的要點

  1. 構造器私有化。例如 private Singleton() {}
  2. 類中有一個 靜態 的單例屬性。
  3. 提供一個 靜態 方法來獲取上述單例。

4 線程不安全的單例模式

4.1 代碼

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

4.2 評價

這樣的單例模式是 線程不安全 的,synchronized 互斥鎖沒有起到應有的作用。只要多個線程都能通過 instance == null 條件,則它們每個線程都會創建一次單例,synchronized 僅僅能保證同一時刻只有一個線程在創建單例罷了。

應該將 判斷賦值 都放到 synchronized 互斥鎖里,就像單例的 第三種實現——懶漢式 ( 線程安全 ) 一樣。

5 JDK中的單例模式

在JDK中,Runtime 類使用了 餓漢式單例,代碼如下:

public class Runtime {private static final Runtime currentRuntime = new Runtime();public static Runtime getRuntime() {return currentRuntime;}private Runtime() {}// ...
}

6 單例模式的類圖及角色

6.1 類圖

alt text
其中,singleton 屬性和 Singleton() 構造器都是 私有的,而 getInstance() 方法是 公開的。此外,singleton 屬性和 getInstance() 方法都是 靜態的

6.2 角色

在單例模式中,只有一個角色 Singleton,它負責 實現返回單例的 靜態 方法

7 推薦的單例模式的實現

  1. 餓漢式
  2. 雙重檢查
  3. 靜態內部類
  4. 枚舉

8 單例模式的使用場景

  • 創建對象耗時過多或耗費資源過多(重量級),但經常用到。
  • 頻繁訪問 數據庫文件 的對象。
  • 工具類對象。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/46453.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/46453.shtml
英文地址,請注明出處:http://en.pswp.cn/web/46453.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【樂吾樂2D可視化組態編輯器】快捷鍵

快捷鍵 樂吾樂2D可視化組態編輯器demo:https://2d.le5le.com/ 快捷鍵描述空格 鼠標拖拽移動畫布鼠標右鍵拖拽移動畫布Ctrl 滾輪縮放畫布Ctrl 點擊 Pen多選Ctrl A全選Ctrl C復制Ctrl X剪切Ctrl V粘貼,alt視圖中心粘貼,shift原位粘貼…

查詢優化 -- UNION 用法

union 不返回重復行(所有字段值相同的行) union all 返回所有行 // 每類最多統計100條 select server_id,count(1) as logs from ( SELECT server_id FROM log WHERE log.type "a" AND server_id1 limit 100 ) UNION select server_id,coun…

谷粒商城-全文檢索-ElasticSearch

1.簡介 一個分布式的開源搜索和分析引擎,可以 秒 級的從海量數據中檢索 主要功能:做數據的檢索和分析(MySQL專攻于數據的持久化存儲與管理CRUD達到百萬以上的數據MSQL就會很慢,海量數據的檢索和分析還是要用ElasticSearch) 用途:我們電商項目里的所有的檢索功能都是由Elasti…

Java中為什么不能直接創建泛型數組

在Java中&#xff0c;不能直接創建泛型數組的主要原因是類型擦除和類型安全問題。 類型擦除 Java中的泛型是通過類型擦除&#xff08;Type Erasure&#xff09;實現的&#xff0c;這意味著在編譯時&#xff0c;泛型類型會被轉換成原始類型&#xff08;如 List<T> 會被轉…

網絡安全-網絡安全及其防護措施9

41.網絡故障排除 網絡故障排除的定義和重要性 網絡故障排除是指通過系統化的方法和工具&#xff0c;識別、診斷和解決網絡中出現的問題&#xff0c;以恢復正常的網絡服務和性能。有效的故障排除可以減少停機時間&#xff0c;提升網絡的穩定性和可靠性。 故障排除的步驟 問題…

基于X86+FPGA+AI數字化醫療設備:全自動尿沉渣檢測儀

助力數字醫療發展&#xff0c;信邁可提供全自動尿沉渣檢測儀專用計算機 隨著信息技術的不斷進步&#xff0c;醫療也進入了一個全新的數字化時代。首先是醫療設備的數字化&#xff0c;大大豐富了醫療信息的內涵和容量&#xff0c;具有廣闊的市場發展前景。 數字化醫療設備&…

使用Redis的SETNX命令實現分布式鎖

什么是分布式鎖 分布式鎖是一種用于在分布式系統中控制多個節點對共享資源進行訪問的機制。在分布式系統中&#xff0c;由于多個節點可能同時訪問和修改同一個資源&#xff0c;因此需要一種方法來確保在任意時刻只有一個節點能夠對資源進行操作&#xff0c;以避免數據不一致或…

白騎士的C++教學高級篇 3.1 文件操作

系列目錄 上一篇&#xff1a;白騎士的C教學進階篇 2.4 標準模板庫&#xff08;STL&#xff09; 文件操作是C編程中的一個重要部分&#xff0c;允許程序與外部存儲設備進行交互&#xff0c;從而實現數據的持久化存儲和讀取。C標準庫提供了豐富的文件操作功能&#xff0c;包括文…

嵌入式香橙派人工智能AI開發板詳細操作與遠程聊天實現

大家好&#xff0c;今天給大分享一個OrangePi AIpro&#xff08;20T&#xff09;采用昇騰作為主控芯片的開發板&#xff0c;開箱以及對應功能的詳細實現。 第一&#xff1a;板子基本介紹 接通電源給對應的開發板上電&#xff0c;觀察其中的現象&#xff0c;如下&#xff1a; 注…

基于HAL庫的stm32的OLED顯示屏顯示(IIC)

OLED OLED&#xff0c;即有機發光二極管( Organic Light Emitting Diode )。OLED由于同時具備自發光&#xff0c;不需背光源、對比度高、厚度薄、視角廣、反應速度快、可用于撓曲性面板、使用溫度范圍廣、構造及制程較簡單等優異之特性&#xff0c;被認為是下一代的平面顯示器…

龍國專利局瑞數6

聲明(lianxi a15018601872) 本文章中所有內容僅供學習交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包內容、敏感網址、數據接口等均已做脫敏處理&#xff0c;嚴禁用于商業用途和非法用途&#xff0c;否則由此產生的一切后果均與作者無關&#xff01; 前言(lianxi a…

富文本中提取信息并去除其中的HTML或XML標簽

要從富文本中提取信息并去除其中的HTML或XML標簽&#xff0c;可以使用不同的編程語言和庫。以下是一些流行語言中的示例方法&#xff1a; 1. Python&#xff08;使用BeautifulSoup&#xff09; BeautifulSoup是一個強大的Python庫&#xff0c;用于從HTML或XML文件中提取數據。…

巨魔商店(TrollStore)介紹與使用指南

iOS巨魔商店&#xff08;TrollStore&#xff09;介紹與使用指南 引言 在iOS系統中&#xff0c;App Store是官方唯一的應用下載渠道&#xff0c;但這也限制了用戶獲取非官方或破解版應用的可能性。然而&#xff0c;巨魔商店&#xff08;TrollStore&#xff09;的出現打破了這一…

配置和保護SSH

使用SSH訪問遠程命令行 描述Secure Shell SSH&#xff08;Secure Shell&#xff09; 是一種網絡協議&#xff0c;用于在不安全的網絡上安全地進行系統管理和數據傳輸。它最初由 Tatu Ylnen 于1995年設計&#xff0c;并成為保護網絡服務免受攻擊的標準。SSH提供了多種功能&…

開始構建我們自己的大語言模型:數據處理部分

關注本專欄&#xff08;NLP簡論&#xff1a;手搓大語言模型實踐&#xff09; 繼續學習從頭編寫、訓練自己的大語言模型。 接上集&#xff0c;本章我們將深入說一下大語言模型數據處理部分的細節&#xff0c;并直接提供本部分的完整代碼。 【配套資源】 暫時的詞匯表&#xff1…

GNN論文粗讀

論文 文章目錄 論文基于異構圖的GNN論文GNN領域論文環境領域GNN論文 隨緣更新 基于異構圖的GNN論文 Distance Information Improves Heterogeneous Graph Neural Networks:DOI: 10.1109/TKDE.2023.3300879 轉導和歸納任務&#xff0c;創新點&#xff1a;異構距離編碼HDE提高GN…

關于Vue中涉及到大量數據的級聯菜單樹狀結構的數據多選勾選頁面卡頓卡死問題

項目場景&#xff1a;如題 提示&#xff1a;有個需求&#xff0c;級聯菜單樹狀結構的數據高達3萬多條&#xff0c;多選&#xff0c;只需要最后一層級value 原因分析&#xff1a;頁面一下子渲染大量數據會導致瀏覽器內存暴漲100%&#xff0c;導致頁面卡死&#xff0c;而且eleme…

常見Linux目錄和配置文件

目錄 /boot/&#xff1a;開機配置文件&#xff0c;也是存放核心vmlinuz的地方 /bin/&#xff1a;系統可執行文件目錄&#xff0c;CentOS7后合并到/usr/bin中&#xff0c;并鏈接過去 /sbin/&#xff1a;系統管理員常用指令存放目錄&#xff0c;例如開關機、磁盤分區等指令&am…

基于SpringBoot+Vue的廣場舞團系統(帶1w+文檔)

基于SpringBootVue的廣場舞團系統(帶1w文檔) 基于SpringBootVue的廣場舞團系統(帶1w文檔) 廣場舞團&#xff0c;為用戶隨時隨地查看廣場舞團信息提供了便捷的方法&#xff0c;更重要的是大大的簡化了管理員管理廣場舞團信息的方式方法&#xff0c;更提供了其他想要了解廣場舞團…

基于Trace的類型特化動態語言JIT編譯

文章目錄 Explain一、簡介二、一個跟蹤運行的示例三、跟蹤樹3.1 Traces類型特化&#xff08;Type specialization&#xff09; 3.2 Trace Trees3.3 黑名單&#xff08;Blacklisting&#xff09; 四、嵌套跟蹤樹4.1 Nesting Algorithm4.2 Blacklisting with Nesting 五、跟蹤樹優…