JAVA多線程并發(fā)下的單例模式應(yīng)用_第1頁(yè)
JAVA多線程并發(fā)下的單例模式應(yīng)用_第2頁(yè)
JAVA多線程并發(fā)下的單例模式應(yīng)用_第3頁(yè)
JAVA多線程并發(fā)下的單例模式應(yīng)用_第4頁(yè)
JAVA多線程并發(fā)下的單例模式應(yīng)用_第5頁(yè)
已閱讀5頁(yè),還剩4頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

本文格式為Word版,下載可任意編輯——JAVA多線程并發(fā)下的單例模式應(yīng)用JAVA多線程并發(fā)下的單例模式應(yīng)用

單例模式理應(yīng)是設(shè)計(jì)模式中對(duì)比簡(jiǎn)樸的一個(gè),也是分外常見的,但是在多線程并發(fā)的環(huán)境下使用卻是不那么簡(jiǎn)樸了,今天我給大家共享一個(gè)在開發(fā)過程中遇到的單例模式的應(yīng)用。

單例模式理應(yīng)是設(shè)計(jì)模式中對(duì)比簡(jiǎn)樸的一個(gè),也是分外常見的,但是在多線程并發(fā)的環(huán)境下使用卻是不那么簡(jiǎn)樸了,今天給大家共享一個(gè)我在開發(fā)過程中遇到的單例模式的應(yīng)用。

首先我們先來(lái)看一下單例模式的定義:

一個(gè)類有且僅有一個(gè)實(shí)例,并且自行實(shí)例化向整個(gè)系統(tǒng)供給。

單例模式的要素:

1.私有的靜態(tài)的.實(shí)例對(duì)象

2.私有的構(gòu)造函數(shù)保證在該類外部,無(wú)法通過new的方式來(lái)創(chuàng)造對(duì)象實(shí)例

3.公有的、靜態(tài)的、訪問該實(shí)例對(duì)象的方法

單例模式分為懶漢形和餓漢式

懶漢式:

應(yīng)用剛啟動(dòng)的時(shí)候,并不創(chuàng)造實(shí)例,當(dāng)外部調(diào)用該類的實(shí)例或者該類實(shí)例方法的時(shí)候,才創(chuàng)造該類的實(shí)例。時(shí)間換空間

優(yōu)點(diǎn):實(shí)例在被使用的時(shí)候才被創(chuàng)造,可以節(jié)省系統(tǒng)資源,表達(dá)了延遲加載的思想。

缺點(diǎn):由于系統(tǒng)剛啟動(dòng)時(shí)且未被外部調(diào)用時(shí),實(shí)例沒有創(chuàng)造;假設(shè)一時(shí)間有多個(gè)線程同時(shí)調(diào)用LazySingleton.getLazyInstance方法很有可能會(huì)產(chǎn)生多個(gè)實(shí)例。

例子:

publicclassSingletonClass

//私有構(gòu)造函數(shù),保證類不能通過new創(chuàng)造

privateSingletonClass

privatestaticSingletonClassinstance=null;

publicstaticSingletonClassgetInstance

ifinstance==null

//創(chuàng)造本類對(duì)象

instance=newSingletonClass;

returninstance;

餓漢式:

應(yīng)用剛啟動(dòng)的時(shí)候,不管外部有沒有調(diào)用該類的實(shí)例方法,該類的實(shí)例就已經(jīng)創(chuàng)造好了。空間換時(shí)間。

優(yōu)點(diǎn):寫法簡(jiǎn)樸,在多線程下也能保證單例實(shí)例的唯一性,不用同步,運(yùn)行效率高。

缺點(diǎn):在外部沒有使用到該類的時(shí)候,該類的實(shí)例就創(chuàng)造了,若該類實(shí)例的創(chuàng)造對(duì)比消耗系統(tǒng)資源,并且外部一向沒有調(diào)用該實(shí)例,那么這片面的系統(tǒng)資源的消耗是沒有意義的。

例子:

publicclassSingleton

//首先自己在內(nèi)部定義自己的一個(gè)實(shí)例,只供內(nèi)部調(diào)用

privatestaticfinalSingletoninstance=newSingleton;

//私有構(gòu)造函數(shù)

privateSingleton

//供給了靜態(tài)方法,外部可以直接調(diào)用

publicstaticSingletongetInstance

returninstance;

下面模擬單例模式在多線程下會(huì)展現(xiàn)的問題

/**

*懶漢式單例類

*/

publicclassLazySingleton

//為了易于模擬多線程下,懶漢式展現(xiàn)的問題,我們?cè)趧?chuàng)造實(shí)例的構(gòu)造函數(shù)里面使當(dāng)前線程暫停了50毫秒

privateLazySingleton

try

Thread.sleep50;

catchInterruptedExceptione

e.printStackTrace;

System.out.println生成LazySingleton實(shí)例一次!;

privatestaticLazySingletonlazyInstance=null;

publicstaticLazySingletongetLazyInstance

iflazyInstance==null

lazyInstance=newLazySingleton;

returnlazyInstance;

測(cè)試代碼:我們?cè)跍y(cè)試代碼里面新建了10個(gè)線程,讓這10個(gè)線程同時(shí)調(diào)用LazySingleton.getLazyInstance方法

publicclassSingletonTest

publicstaticvoidmainString[]args

//創(chuàng)造十個(gè)線程調(diào)

forinti=0;i10;i++

newThread

@Override

publicvoidrun

LazySingleton.getLazyInstance;

.start;

結(jié)果:

生成LazySingleton實(shí)例一次!

生成LazySingleton實(shí)例一次!

生成LazySingleton實(shí)例一次!

生成LazySingleton實(shí)例一次!

生成LazySingleton實(shí)例一次!

生成LazySingleton實(shí)例一次!

生成LazySingleton實(shí)例一次!

生成LazySingleton實(shí)例一次!

生成LazySingleton實(shí)例一次!

生成LazySingleton實(shí)例一次!

可以看出單例模式懶漢式在多線程的并發(fā)下也會(huì)展現(xiàn)問題,

分析一下:多個(gè)線程同時(shí)訪問上面的懶漢式單例,現(xiàn)在有兩個(gè)線程A和B同時(shí)訪問LazySingleton.getLazyInstance方法。

假設(shè)A先得到CPU的時(shí)間切片,A執(zhí)行到iflazyInstance==null時(shí),由于lazyInstance之前并沒有實(shí)例化,所以lazyInstance==null為true,在還沒有執(zhí)行實(shí)例創(chuàng)造的時(shí)候

此時(shí)CPU將執(zhí)行時(shí)間分給了線程B,線程B執(zhí)行到iflazyInstance==null時(shí),由于lazyInstance之前并沒有實(shí)例化,所以lazyInstance==null為true,線程B持續(xù)往下執(zhí)行實(shí)例的創(chuàng)造過程,線程B創(chuàng)造完實(shí)例之后,返回。

此時(shí)CPU將時(shí)間切片分給線程A,線程A接著開頭執(zhí)行實(shí)例的創(chuàng)造,實(shí)例創(chuàng)造完之后便返回。由此看線程A和線程B分別創(chuàng)造了一個(gè)實(shí)例存在2個(gè)實(shí)例了,這就導(dǎo)致了單例的失效。

解決手段:我們可以在getLazyInstance方法上加上synchronized使其同步,但是這樣一來(lái),會(huì)降低整個(gè)訪問的速度,而且每次都要判斷。

那么有沒有更好的方式來(lái)實(shí)現(xiàn)呢?我們可以考慮使用雙重檢查加鎖的方式來(lái)實(shí)現(xiàn),就可以既實(shí)現(xiàn)線程安好,又能夠使性能不受到很大的影響。我們看看概括解決代碼

publicclassLazySingleton

privateLazySingleton

try

Thread.sleep50;

catchInterruptedExceptione

e.printStackTrace;

System.out.println生成LazySingleton實(shí)例一次!;

privatestaticLazySingletonlazyInstance=null;

publicstaticLazySingletongetLazyInstance

//先檢查實(shí)例是否存在,假設(shè)不存在才進(jìn)入下面的同步塊

iflazyInstance==null

//同步塊,線程安好地創(chuàng)造實(shí)例

synchronizedLazySingleton.class

//再次檢查實(shí)例是否存在,假設(shè)不存在才真正地創(chuàng)造實(shí)例

iflazyInstance==null

lazyInstance=newLazySingleton;

returnlazyInstance;

這樣我們就可以在多線程并發(fā)下安好應(yīng)用單例模式中的懶漢模式。這種方法在代碼上可能就不怎么美觀,我們可以優(yōu)雅的使用一個(gè)內(nèi)部類來(lái)維護(hù)單例類的實(shí)例,下面看看代碼

publicclassGracefulSingleton

privateGracefulSingleton

System.out.println創(chuàng)造GracefulSingleton實(shí)例一次!;

//類級(jí)的內(nèi)部類,也就是靜態(tài)的成員式內(nèi)部類,該內(nèi)部類的實(shí)例與外部類的實(shí)例沒有綁定關(guān)系,而且只有被調(diào)用到才會(huì)裝載,從而實(shí)現(xiàn)了延遲加載

privatestaticclassSingletonHoder

//靜態(tài)初始化器,由JVM來(lái)保證線程安好

privatestaticGracefulSingletoninstance=newGracefulSingleton;

publicstaticGracefulSingletongetInstance

returnSingletonHoder.instance;

說一下我在實(shí)際開發(fā)中的場(chǎng)景:為了程序的高效率使用多線程并發(fā),然而是循環(huán)調(diào)用,可能導(dǎo)致創(chuàng)造線程數(shù)過多,考慮采用線程池管理,這時(shí)候創(chuàng)造線程池依舊是處于循環(huán)調(diào)用中,也可能導(dǎo)致多個(gè)線程池,這時(shí)候就考慮使用單例模式。

源代碼:

publicclassThreadPoolFactoryUtil

privateExecutorServiceexecutorService;

//在構(gòu)造函數(shù)中創(chuàng)造線程池

privateThreadPoolFactoryUtil

//獲取系統(tǒng)處理器個(gè)數(shù),作為線程池?cái)?shù)量

intnThreads=Runtime.getRuntime.availableProcessors;

executorService=Executors.newFixedThreadPoolnThreads;

//定義一個(gè)靜態(tài)內(nèi)部類,內(nèi)部定義靜態(tài)成員創(chuàng)造外部類實(shí)例

privatestaticclassSingletonContainer

privatestaticThreadPoolFactoryUtilutil=newThreadPoolFactoryUtil;

//獲取本類對(duì)象

publicstaticThreadPoolFactoryUtilgetUtil

returnSingletonContainer.util;

publicExecutorServicegetExecutorService

returnexecutorService;

涉及到一個(gè)靜態(tài)內(nèi)部類,我們看看靜態(tài)內(nèi)部類的特點(diǎn):

1、靜態(tài)內(nèi)部類無(wú)需憑借于外部類,它可以獨(dú)立于

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論