Java單例模式及開發應用場景
所謂單例,指的就是單例項,有且僅有一個類例項,這個單例不應該由人來控制,而應該由程式碼來限制,強制單例。
單例有其獨有的使用場景,一般是對於那些業務邏輯上限定不能多例只能單例的情況,例如:類似於計數器之類的存在,一般都需要使用一個例項來進行記錄,若多例計數則會不準確。
其實單例就是那些很明顯的使用場合,沒有之前學習的那些模式所使用的複雜場景,只要你需要使用單例,那你就使用單例,簡單易理解。
1、常見的單例模式有兩種建立方式:所謂餓懶漢式與餓漢式
(1)懶漢式
何為懶?顧名思義,就是不做事,這裡也是同義,懶漢式就是不在系統載入時就建立類的單例,而是在第一次使用例項的時候再建立。
詳見下方程式碼示例:
1 public class LHanDanli { 2 //定義一個私有類變數來存放單例,私有的目的是指外部無法直接獲取這個變數,而要使用提供的公共方法來獲取 3 private static LHanDanli dl = null; 4 //定義私有構造器,表示只在類內部使用,亦指單例的例項只能在單例類內部建立 5 private LHanDanli(){} 6 //定義一個公共的公開的方法來返回該類的例項,由於是懶漢式,需要在第一次使用時生成例項,所以為了執行緒安全,使用synchronized關鍵字來確保只會生成單例 7 public staticsynchronized LHanDanli getInstance(){ 8 if(dl == null){ 9 dl = new LHanDanli(); 10 } 11 return dl; 12 } 13 }
(2)餓漢式
又何為餓?餓者,飢不擇食;但凡有食,必急食之。此處同義:在載入類的時候就會建立類的單例,並儲存在類中。
詳見下方程式碼示例:
1 public class EHanDanli { 2 //此處定義類變數例項並直接例項化,在類載入的時候就完成了例項化並儲存在類中 3 privatestatic EHanDanli dl = new EHanDanli(); 4 //定義無參構造器,用於單例例項 5 private EHanDanli(){} 6 //定義公開方法,返回已建立的單例 7 public static EHanDanli getInstance(){ 8 return dl; 9 } 10 }
2、雙重加鎖機制
何為雙重加鎖機制?
在懶漢式實現單例模式的程式碼中,有使用synchronized關鍵字來同步獲取例項,保證單例的唯一性,但是上面的程式碼在每一次執行時都要進行同步和判斷,無疑會拖慢速度,使用雙重加鎖機制正好可以解決這個問題:
1 public class SLHanDanli { 2 private static volatile SLHanDanli dl = null; 3 private SLHanDanli(){} 4 public static SLHanDanli getInstance(){ 5 if(dl == null){ 6 synchronized (SLHanDanli.class) { 7 if(dl == null){ 8 dl = new SLHanDanli(); 9 } 10 } 11 } 12 return dl; 13 } 14 }
看了上面的程式碼,有沒有感覺很無語,雙重加鎖難道不是需要兩個synchronized進行加鎖的嗎?
......
其實不然,這裡的雙重指的的雙重判斷,而加鎖單指那個synchronized,為什麼要進行雙重判斷,其實很簡單,第一重判斷,如果單例已經存在,那麼就不再需要進行同步操作,而是直接返回這個例項,如果沒有建立,才會進入同步塊,同步塊的目的與之前相同,目的是為了防止有兩個呼叫同時進行時,導致生成多個例項,有了同步塊,每次只能有一個執行緒呼叫能訪問同步塊內容,當第一個搶到鎖的呼叫獲取了例項之後,這個例項就會被建立,之後的所有呼叫都不會進入同步塊,直接在第一重判斷就返回了單例。至於第二個判斷,個人感覺有點查遺補漏的意味在內(期待高人高見)。
不論如何,使用了雙重加鎖機制後,程式的執行速度有了顯著提升,不必每次都同步加鎖。
其實我最在意的是volatile的使用,volatile關鍵字的含義是:被其所修飾的變數的值不會被本地執行緒快取,所有對該變數的讀寫都是直接操作共享記憶體來實現,從而確保多個執行緒能正確的處理該變數。該關鍵字可能會遮蔽掉虛擬機器中的一些程式碼優化,所以其執行效率可能不是很高,所以,一般情況下,並不建議使用雙重加鎖機制,酌情使用才是正理!
3、類級內部類方式
餓漢式會佔用較多的空間,因為其在類載入時就會完成例項化,而懶漢式又存在執行速率慢的情況,雙重加鎖機制呢?又有執行效率差的毛病,有沒有一種完美的方式可以規避這些毛病呢?
貌似有的,就是使用類級內部類結合多執行緒默認同步鎖,同時實現延遲載入和執行緒安全。
1 public class ClassInnerClassDanli { 2 public static class DanliHolder{ 3 private static ClassInnerClassDanli dl = new ClassInnerClassDanli(); 4 } 5 private ClassInnerClassDanli(){} 6 public static ClassInnerClassDanli getInstance(){ 7 return DanliHolder.dl; 8 } 9 }
如上程式碼,所謂類級內部類,就是靜態內部類,這種內部類與其外部類之間並沒有從屬關係,載入外部類的時候,並不會同時載入其靜態內部類,只有在發生呼叫的時候才會進行載入,載入的時候就會建立單例例項並返回,有效實現了懶載入(延遲載入),至於同步問題,我們採用和餓漢式同樣的靜態初始化器的方式,藉助JVM來實現執行緒安全。
其實使用靜態初始化器的方式會在類載入時建立類的例項,但是我們將例項的建立顯式放置在靜態內部類中,它會導致在外部類載入時不進行例項建立,這樣就能實現我們的雙重目的:延遲載入和執行緒安全。
一、單例模式:在spring中其實是scope(作用範圍)引數的預設設定值每個bean定義只生成一個物件例項,每次getBean請求獲得的都是此例項
單例模式分為餓漢模式和懶漢模式,
餓漢模式 | spring singleton的預設是餓漢模式:啟動容器時(即例項化容器時),為所有spring配置檔案中定義的bean都生成一個例項 |
懶漢模式 | 在第一個請求時才生成一個例項,以後的請求都呼叫這個例項 spring singleton設定為懶漢模式: <beans default-lazy-init="true"> |
singleton和prototype的比較
singleton:
xml配置檔案: <bean id="dvdTypeDAO" class="com.terana.hibernate.impl.DvdTypeDAOImpl" /> |
測試程式碼: ctx = new ClassPathXmlApplicationContext("spring-hibernate-mysql.xml"); DvdTypeDAO tDao1 = (DvdTypeDAO)ctx.getBean("dvdTypeDAO"); DvdTypeDAO tDao2 = (DvdTypeDAO)ctx.getBean("dvdTypeDAO"); |
執行: true [email protected] [email protected] 說明前後兩次getBean()獲得的是同一例項,說明spring預設是單例 |
prototype:
<bean id="dvdTypeDAO" class="com.terana.hibernate.impl.DvdTypeDAOImpl" scope="prototype" /> |
執行同樣的測試程式碼 |
執行: false [email protected] [email protected] 說明scope="prototype"後,每次getBean()的都是不同的新例項 |
相關推薦
Java單例模式及開發應用場景
所謂單例,指的就是單例項,有且僅有一個類例項,這個單例不應該由人來控制,而應該由程式碼來限制,強制單例。 單例有其獨有的使用場景,一般是對於那些業務邏輯上限定不能多例只能單例的情況,例如:類似於計數器之類的存在,一般都需要使用一個例項來進行記錄,若多例計數則會
設計模式之單例模式>>應用場景及實現
arr unit 應用 lose sys time 初始 sin turn 定義 單例模式(Singleton),也叫單子模式,是一種常用的軟件設計模式。對於系統而言該實例有且僅有一個。 應用場景 線程池、數據庫池、用於對系統做初始化的實例,提供給關聯系統調用的接口(
建立型:單例模式及相關應用
文章目錄 單例模式(Singleton) 優缺點 重點 懶漢式實現 執行緒不安全 synchronized關鍵字 雙重校驗鎖 靜態內部類 餓漢式實現 單例模式
Java單例模式及建立單例模式的多執行緒問題 volatile synchronized 關鍵字
接下來,說說我對多執行緒中volitile 和 synchronized的理解 這兩個關鍵字都是java內建的用於實現執行緒同步的機制,其中: volitile用於修飾變數,用於同步主記憶體和執行緒儲存中的變數值,但是volitile使用應牢記 —— 只有在狀態真正獨立
java 單例模式及在SSH框架中運用
定義: 確保某一個類只有一個例項,而且自動例項化並向整個系統提供這個例項。 程式碼: Singleton類稱為單例類,通過使用private的建構函式確保了在一個應用中只產生一個例項,並且是自行例項化的。 Java程式碼 /** * 執行緒安全的
設計模式 | 單例模式及典型應用
單例是最常見的設計模式之一,實現的方式非常多,同時需要注意的問題也非常多。 本文主要內容: 介紹單例模式 介紹單例模式的N中寫法 單例模式的安全性 序列化攻擊 反射攻擊 單例模式總結 介紹單例模式的典型應用
Java單例模式及延遲載入
單例模式是 軟體開發中非常重要的模式之一。絕大多數的軟體專案中都會用到單例模式。單例模式應用的好與壞在高併發訪問的情況下效能差異較為明顯。下面我們來看一下單例模式的具體解釋。 描述:單例模式許多時候是
java單例模式雙重檢驗鎖的優缺點?還有哪些實現方式?列舉一些使用場景
2018年7月18日,在專案程式碼中看到單例模式,總結一下單例模式的知識點. 單例模式的概念: 在應用程式的生命週期中,在任意時刻,引用某個類的例項都是同一個.在一個系統中有些類只需要有一個全域性物件,統一管理系統行為和執行某些操作.例如在使用hibernate時,ses
一個JAVA單例模式的典型錯誤應用的分析和解決方法
問題來自論壇,其程式碼如下:[java] view plain copy print?import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; imp
Java單例模式之懶漢模式及餓漢模式
單例模式 單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。 這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一
JAVA中的餓漢式和飽漢式單例模式及jdk中Runtime類的單例模式實現方式詳解
一、描述 單例模式是一種非常常見的設計模式,即一個類只能有一個物件(例項),一般通過將該類的構造器私有化,來阻止在該類外建立該類的物件,並提供給外界一個唯一的物件(這個物件在該類中建立)。 java中的單例模式常見的有兩種實現方式,一種是惡漢方式,即將該類物件
Java設計模式之單例模式及在Android中的重要使用
之前在開發中老用到一些設計模式可是呢又不是很懂,於是狠下心來琢磨一番。下面是我琢磨後總結的,希望對您有用。如果發現了問題,請幫忙指正。 一、單例模式是什麼? 單例模式最初的定義出現於《設計模式》:“保證一個類僅有一個例項,並提供一個訪問它的全域性
Java單例模式
class auth pre light java on() ack private gets package singleton; /** * 單例模式 * @author pengYi * */ public class Singleton { priva
java單例模式等一些程序的寫法....持續更新...
new tor zed bsp 更新 餓漢式 blog stat cto 一、單例模式的寫法: public class MyFactory { /** * 餓漢式 */ private static MyFactory instanc
老男孩教育每日一題-第83天-binlog是什麽?記錄的什麽?有幾種工作模式及企業應用場景
mysql binlog 每日一題 參考答案含義binlog:是用於記錄所有更新了數據的操作語句,語句以事件的形式保存,它描述數據的更改過程作用:用於實時備份數據,數據庫的主從復制log_bin 打開記錄binlog功能binlog的查看mysqlbinlog /home/mysql/binlog
單例模式及常見寫法分析(設計模式01)
啟動 nes 成員變量 額外 log 序列 spa tar adl 保證一個類僅有一個實例。並提供一個該實例的全局訪問點。 ——《設計模式》單例模式的概念非常easy。以下以C#語言為樣例,列出常見單例寫法的優缺點。1、簡單實現 public s
java 單例模式
多線程安全 except detail 追加 earch 繼承 好處 config 什麽是 單例模式(Singleton)也叫單態模式,是設計模式中最為簡單的一種模式,甚至有些模式大師都不稱其為模式,稱其為一種實現技巧,因為設計模式講究對象之間的關系的抽象,而單例模式只有自
c++的單例模式及c++11對單例模式的優化
on() end per let namespace lease 是否 存在 建立 單例模式 單例模式,可以說設計模式中最常應用的一種模式了,據說也是面試官最喜歡的題目。但是如果沒有學過設計模式的人,可能不會想到要去應用單例模式,面對單例模式適用的情況,可能會優先考慮使用全
java單例模式的心得
開發人員 性能 文章 人員 外部 訪問 單例 鎖定 初始化 由於設計模式對於java高級開發人員來說是非常重要的,網上也有很多關於設計模式的文章,博客等。所以,首先我對相對簡單的單例模式做一個簡單的總結。 一、實現方式 單例模式的實現方式有3種,分別是餓漢式
Java單例模式深入詳解
protected test 異常 except while 深入 bject his 不一致 Java單例模式深入詳解 一.問題引入 偶然想想到的如果把Java的構造方法弄成private,那裏面的成員屬性是不是只有通過static來訪問呢;如果構造方法是privat