單例設計模式精講(餓漢式和懶漢式實現的重要方法)

目錄

什么叫做單例模式?

餓漢式和懶漢式的區別?

餓漢式-方式1(靜態變量方式)

餓漢式-方式2(靜態代碼塊方式)

懶漢式-方式1(線程不安全)

懶漢式-方式2(線程安全)

懶漢式-方式3(雙重檢查鎖)

懶漢式-方式4(靜態內部類方式)


什么叫做單例模式?


????????涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供 了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。


餓漢式和懶漢式的區別?


? ? ? ? 餓漢式:類加載就會導致該單實例對象被創建
? ? ? ? 懶漢式:類加載不會導致該單實例對象被創建,而是首次使用該對象時才會創建
? ? ? ? 導致類加載的情況:new 對象,創建子類,調用靜態屬性
? ? ? ? 類加載是什么意思:就是把你的變量和方法存在內存當中
? ? ? ? 代碼區別如下:
? ? ? ? 人話來說就是創建對象的時機不一樣,如果看不懂的話建議去補java基礎靜態這一塊的知識

//餓漢式
public class Singleton {private Singleton(){}
//    提前創建好單列對象;private static Singleton instance = new Singleton();public static Singleton getInstance(){return instance;}}
//測試代碼:
public class Test {public static void main (String[] args) {//因為這里調用的是靜態方法,所以導致類加載,就會執行 new Singleton();從而創建對象//導致類加載的情況:new 對象,創建子類,調用靜態屬性Singleton instance = Singleton.getInstance();Singleton instance1 = Singleton.getInstance();System.out.println(instance==instance1);}
}
============================================================================
//餓漢式
public class Singleton {private Singleton(){}private static Singleton instance;public static Singleton getInstance(){if (instance==null){//調用的時候才創建對象//判短對象為空才創建對象instance=new Singleton();}return instance;}
}
public class Test {public static void main (String[] args) {//調用方法的時候才創建對象Singleton instance = Singleton.getInstance();Singleton instance1 = Singleton.getInstance();System.out.println(instance==instance1);}
}

餓漢式-方式1(靜態變量方式)
?

/**
* 餓漢式
* 靜態變量創建類的對象
*/
public class Singleton {
//私有構造方法
private Singleton() {}
//在成員位置創建該類的對象
private static Singleton instance = new Singleton();
//對外提供靜態方法獲取該對象
public static Singleton getInstance() {
return instance;
}
}

缺點:
該方式在成員位置聲明Singleton類型的靜態變量,并創建Singleton類的對象instance。 instance對象是隨著類的加載而創建的。如果該對象足夠大的話,而一直沒有使用就會造成內存 的浪費。


餓漢式-方式2(靜態代碼塊方式)
?

/**
* 惡漢式
* 在靜態代碼塊中創建該類對象
*/
public class Singleton {
//私有構造方法
private Singleton() {}
//在成員位置創建該類的對象
private static Singleton instance;
static {
instance = new Singleton();
}
//對外提供靜態方法獲取該對象
public static Singleton getInstance() {
return instance;
}
}

缺點:
該方式在成員位置聲明Singleton類型的靜態變量,而對象的創建是在靜態代碼塊中,也是對著 類的加載而創建。所以和餓漢式的方式1基本上一樣,當然該方式也存在內存浪費問題。


懶漢式-方式1(線程不安全)

/**
* 懶漢式
* 線程不安全
*/
public class Singleton {
//私有構造方法
private Singleton() {}
//在成員位置創建該類的對象
private static Singleton instance;
//對外提供靜態方法獲取該對象
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}

缺點:
從上面代碼我們可以看出該方式在成員位置聲明Singleton類型的靜態變量,并沒有進行對象的 賦值操作,那么什么時候賦值的呢?當調用getInstance()方法獲取Singleton類的對象的時 候才創建Singleton類的對象,這樣就實現了懶加載的效果。但是,如果是多線程環境,會出現 線程安全問題。


懶漢式-方式2(線程安全)
?

/**
* 懶漢式
* 線程安全
*/
public class Singleton {
//私有構造方法
private Singleton() {}
//在成員位置創建該類的對象
private static Singleton instance;
//對外提供靜態方法獲取該對象
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}

缺點:
該方式也實現了懶加載效果,同時又解決了線程安全問題。但是在getInstance()方法上添加了 synchronized關鍵字,導致該方法的執行效果特別低。從上面代碼我們可以看出,其實就是在 初始化instance的時候才會出現線程安全問題,一旦初始化完成就不存在了。

就是每個現場都會拿到鎖,導致效率降低,應該是當沒有獲取對象的誰時候拿到鎖。

?

懶漢式-方式3(雙重檢查鎖)
?

public class Singleton {private Singleton(){}//聲明一個Singleton類型的變量private static Singleton instance;public static Singleton getInstance(){if (instance==null){//為空的時候才會拿到鎖synchronized (Singleton.class){if (instance==null){instance=new Singleton();}}}return instance;}
}

雙重檢查鎖模式是一種非常好的單例實現模式,解決了單例、性能、線程安全問題,上面的雙重檢 測鎖模式看上去完美無缺,其實是存在問題,在多線程的情況下,可能會出現空指針問題,出現問 題的原因是JVM在實例化對象的時候會進行優化和指令重排序操作。 要解決雙重檢查鎖模式帶來空指針異常的問題,只需要使用 volatile 關鍵字, volatile 關 鍵字可以保證可見性和有序性。
?

懶漢式-方式4(靜態內部類方式)

?

public class Singleton {
//私有構造方法
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
//對外提供靜態方法獲取該對象
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

?第一次加載Singleton類時不會去初始化INSTANCE,只有第一次調用getInstance,虛擬機加 載SingletonHolder 并初始化INSTANCE,這樣不僅能確保線程安全,也能保證 Singleton 類的唯一性。 小結: 靜態內部類單例模式是一種優秀的單例模式,是開源項目中比較常用的一種單例模式。在沒有加任 何鎖的情況下,保證了多線程下的安全,并且沒有任何性能影響和空間的浪費。

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

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

相關文章

FifthOne:用于矢量搜索的計算機視覺接口

一、說明 數據太多了。數據湖和數據倉庫;廣闊的像素牧場和充滿文字的海洋。找到正確的數據就像大海撈針一樣!如果你喜歡開源機器學習庫 FiftyOne,矢量搜索引擎通過將復雜數據(圖像的原始像素值、文本文檔中的字符)轉換為稱為嵌入矢…

PHP報錯:未定義常量的解決方法!

PHP報錯:未定義常量的解決方法! 在PHP編程中,我們經常會遇到常量未定義的錯誤。這種錯誤通常會在代碼中使用未定義的常量時發生。本文將介紹常量的概念以及如何解決未定義常量的問題。 首先,讓我們來了解什么是常量。在PHP中&am…

大數據平臺運維實訓室建設方案

一、概況 本實訓室的主要目的是培養大數據平臺運維項目的實踐能力,以數據計算、分析、挖掘和可視化的案例訓練為輔助。同時,實訓室也承擔相關考評員與講師培訓考試、學生認證培訓考試、社會人員認證培訓考試、大數據技能大賽訓練、大數據專業課程改革等多項任務。 實訓室旨在培…

無人機跟隨一維高度避障場景--邏輯分析

無人機跟隨一維高度避障場景--邏輯分析 1. 源由2. 視頻3. 問題3.1 思維發散3.2 問題收斂 4. 圖示4.1 水平模式4.2 下坡模式4.3 上坡模式4.4 碰撞分析 5. 總結5.1 一維高度避障場景5.2 業界跟隨產品5.3 APM集成跟隨示意圖一:示意圖二:示意圖三&#xff1a…

Java算法_ 驗證二叉搜索樹(LeetCode_Hot100)

題目描述: 給你一個二叉樹的根節點 ,判斷其是否是一個有效的二叉搜索樹。root 有效 二叉搜索樹定義如下: 節點的左子樹只包含 小于 當前節點的數。 節點的右子樹只包含 大于 當前節點的數。 所有左子樹和右子樹自身必須也是二叉搜索樹。 獲得…

【TypeScript】tsc -v 報錯 —— 在此系統上禁止運行腳本

在 VS Code 終端中執行 tsc -v ,報錯 —— 在此系統上禁止運行腳本 然后 windows x ,打開終端管理員,出現同樣的問題 解決方法: 終端(管理員)執行以下命令: 出現 RemoteSigned 則代表更改成功…

11,模板泛化、模板特化、所占字節數、繼承實現模板展開、using循環命名展開可變參數

模板泛化、模板特化、所占字節數、繼承實現模板展開、using循環命名展開可變參數 模板泛化模板特化模板全特化通過模板偏特化獲取類型所占字節數通過模板偏特化和宏獲取類型所占字節數...ParamTypes和ParamTypes...的區別 通過繼承實現模板展開using 通過using循環命名的方式來…

開發一個文生圖的功能

文章目錄 效果開發環境原理核心代碼代碼倉庫問題效果 開發環境 Python 3.10PyCharm原理 借助開源項目stable-diffusion,通過該項目封裝python庫diffusers,可以輕易的實現文生圖的功能。 關于更多diffusers的功能請訪問:https://huggingface.co/docs/diffusers/index 核心代…

css樣式表屬性

文章目錄 css樣式表屬性colorbackground-colorfont-sizefont-weightfont-familyfont-styletext-decorationtext-indentline-height(line-height的概念)width、heightletter-spacingtext-aligndirectionwriting-modefont-variantborder-radiusopacitycursorvertical-alignmin-wi…

【數據結構與算法】十大經典排序算法-歸并排序

🌟個人博客:www.hellocode.top 🏰Java知識導航:Java-Navigate 🔥CSDN:HelloCode. 🌞知乎:HelloCode 🌴掘金:HelloCode ?如有問題,歡迎指正&#…

如何用輸入函數為數組賦值

在編寫程序時我們經常使用數組,而數組的大小可能是很大的但是我們并不需要為每個元素都自己賦值,我們可能會自定義輸入數組元素個數,我們應該如何實現通過輸入函數為數組賦值呢? 目錄 第一種: 第二種: 第一…

大數據bug-sqoop(二:sqoop同步mysql數據到hive進行字段限制。)

一:sqoop腳本解析。 #!/bin/sh mysqlHost$1 mysqlUserName$2 mysqlUserPass$3 mysqlDbName$4 sql$5 split$6 target$7 hiveDbName$8 hiveTbName$9 partFieldName${10} inputDate${11}echo ${mysqlHost} echo ${mysqlUserName} echo ${mysqlUserPass} ec…

OpenCV之remap的使用

OpenCV中使用remap實現圖像的重映射。 重映射是指將圖像中的某一像素值賦值到指定位置的操作:g(x,y) f ( h(x,y) ), 在這里, g( ) 是目標圖像, f() 是源圖像, 而h(x,y) 是作用于 (x,y) 的映射方法函數。為了完成映射過程, 需要獲得一些插值為…

TypeError: a bytes-like object is required, not ‘str‘

raceback (most recent call last): File "D:\pycharmcode\client.py", line 12, in <module> tcp_socket.send(send_data) TypeError: a bytes-like object is required, not str 使用socket進行ubuntu與windows通信時&#xff0c;發送數據時報了以上錯…

LeetCode 面試題 01.04. 回文排列

文章目錄 一、題目二、C# 題解 一、題目 給定一個字符串&#xff0c;編寫一個函數判定其是否為某個回文串的排列之一。 回文串是指正反兩個方向都一樣的單詞或短語。排列是指字母的重新排列。 回文串不一定是字典當中的單詞。 點擊此處跳轉題目。 示例1&#xff1a; 輸入&…

CSS3:圖片邊框

簡介 圖片也可以作為邊框&#xff0c;以下是實例演示 注意 實現該效果必須添加border樣式&#xff0c;且必須位于border-image-socure之前否則不會生效 實例 <html lang"en"><head><style>p {width: 600px;margin: 200px auto;border: 30px soli…

maven工具-maven的使用-鏡像倉庫、本地倉、IDEA使用maven

Maven 一、為什么使用maven 添加第三方jar包jar包之間的依賴關系處理jar包之間的沖突獲取第三方jar包將項目拆分成多個工程模塊實現項目的分布式部署 二、maven簡介 ? Maven項目對象模型(POM)&#xff0c;可以通過一小段描述信息來管理項目的構建&#xff0c;報告和文檔的…

2023.8 - java - 對象和類

public class Dog {String breed;int size;String colour;int age;void eat() {}void run() {}void sleep(){}void name(){} } 一個類可以包含以下類型變量&#xff1a; 局部變量&#xff1a;在方法、構造方法或者語句塊中定義的變量被稱為局部變量。變量聲明和初始化都是在方…

基于STM32標準庫智能風扇設計

目錄 一&#xff0c;前言 二&#xff0c;系統方案選擇 三&#xff0c;實體展示 工程分類 四&#xff0c;相關代碼 PWM.c PWM.h AD.c AD.h 電機驅動程序 舵機驅動 一&#xff0c;前言 當今生活中&#xff0c;風扇已成為人們解暑的重要工具&#xff0c;然而使用風扇緩解…

CentOS系統環境搭建(九)——centos系統下使用docker部署項目

centos系統環境搭建專欄&#x1f517;點擊跳轉 關于Docker-compose安裝請看CentOS系統環境搭建&#xff08;三&#xff09;——Centos7安裝Docker&Docker Compose&#xff0c;該文章同樣收錄于centos系統環境搭建專欄。 Centos7部署項目 采用前后端分離的形式部署。使用Do…