JAVA多線程并發下的單例模式應用_第1頁
JAVA多線程并發下的單例模式應用_第2頁
JAVA多線程并發下的單例模式應用_第3頁
JAVA多線程并發下的單例模式應用_第4頁
JAVA多線程并發下的單例模式應用_第5頁
已閱讀5頁,還剩4頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

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

單例模式理應是設計模式中對比簡樸的一個,也是分外常見的,但是在多線程并發的環境下使用卻是不那么簡樸了,今天我給大家共享一個在開發過程中遇到的單例模式的應用。

單例模式理應是設計模式中對比簡樸的一個,也是分外常見的,但是在多線程并發的環境下使用卻是不那么簡樸了,今天給大家共享一個我在開發過程中遇到的單例模式的應用。

首先我們先來看一下單例模式的定義:

一個類有且僅有一個實例,并且自行實例化向整個系統供給。

單例模式的要素:

1.私有的靜態的.實例對象

2.私有的構造函數保證在該類外部,無法通過new的方式來創造對象實例

3.公有的、靜態的、訪問該實例對象的方法

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

懶漢式:

應用剛啟動的時候,并不創造實例,當外部調用該類的實例或者該類實例方法的時候,才創造該類的實例。時間換空間

優點:實例在被使用的時候才被創造,可以節省系統資源,表達了延遲加載的思想。

缺點:由于系統剛啟動時且未被外部調用時,實例沒有創造;假設一時間有多個線程同時調用LazySingleton.getLazyInstance方法很有可能會產生多個實例。

例子:

publicclassSingletonClass

//私有構造函數,保證類不能通過new創造

privateSingletonClass

privatestaticSingletonClassinstance=null;

publicstaticSingletonClassgetInstance

ifinstance==null

//創造本類對象

instance=newSingletonClass;

returninstance;

餓漢式:

應用剛啟動的時候,不管外部有沒有調用該類的實例方法,該類的實例就已經創造好了。空間換時間。

優點:寫法簡樸,在多線程下也能保證單例實例的唯一性,不用同步,運行效率高。

缺點:在外部沒有使用到該類的時候,該類的實例就創造了,若該類實例的創造對比消耗系統資源,并且外部一向沒有調用該實例,那么這片面的系統資源的消耗是沒有意義的。

例子:

publicclassSingleton

//首先自己在內部定義自己的一個實例,只供內部調用

privatestaticfinalSingletoninstance=newSingleton;

//私有構造函數

privateSingleton

//供給了靜態方法,外部可以直接調用

publicstaticSingletongetInstance

returninstance;

下面模擬單例模式在多線程下會展現的問題

/**

*懶漢式單例類

*/

publicclassLazySingleton

//為了易于模擬多線程下,懶漢式展現的問題,我們在創造實例的構造函數里面使當前線程暫停了50毫秒

privateLazySingleton

try

Thread.sleep50;

catchInterruptedExceptione

e.printStackTrace;

System.out.println生成LazySingleton實例一次!;

privatestaticLazySingletonlazyInstance=null;

publicstaticLazySingletongetLazyInstance

iflazyInstance==null

lazyInstance=newLazySingleton;

returnlazyInstance;

測試代碼:我們在測試代碼里面新建了10個線程,讓這10個線程同時調用LazySingleton.getLazyInstance方法

publicclassSingletonTest

publicstaticvoidmainString[]args

//創造十個線程調

forinti=0;i10;i++

newThread

@Override

publicvoidrun

LazySingleton.getLazyInstance;

.start;

結果:

生成LazySingleton實例一次!

生成LazySingleton實例一次!

生成LazySingleton實例一次!

生成LazySingleton實例一次!

生成LazySingleton實例一次!

生成LazySingleton實例一次!

生成LazySingleton實例一次!

生成LazySingleton實例一次!

生成LazySingleton實例一次!

生成LazySingleton實例一次!

可以看出單例模式懶漢式在多線程的并發下也會展現問題,

分析一下:多個線程同時訪問上面的懶漢式單例,現在有兩個線程A和B同時訪問LazySingleton.getLazyInstance方法。

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

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

此時CPU將時間切片分給線程A,線程A接著開頭執行實例的創造,實例創造完之后便返回。由此看線程A和線程B分別創造了一個實例存在2個實例了,這就導致了單例的失效。

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

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

publicclassLazySingleton

privateLazySingleton

try

Thread.sleep50;

catchInterruptedExceptione

e.printStackTrace;

System.out.println生成LazySingleton實例一次!;

privatestaticLazySingletonlazyInstance=null;

publicstaticLazySingletongetLazyInstance

//先檢查實例是否存在,假設不存在才進入下面的同步塊

iflazyInstance==null

//同步塊,線程安好地創造實例

synchronizedLazySingleton.class

//再次檢查實例是否存在,假設不存在才真正地創造實例

iflazyInstance==null

lazyInstance=newLazySingleton;

returnlazyInstance;

這樣我們就可以在多線程并發下安好應用單例模式中的懶漢模式。這種方法在代碼上可能就不怎么美觀,我們可以優雅的使用一個內部類來維護單例類的實例,下面看看代碼

publicclassGracefulSingleton

privateGracefulSingleton

System.out.println創造GracefulSingleton實例一次!;

//類級的內部類,也就是靜態的成員式內部類,該內部類的實例與外部類的實例沒有綁定關系,而且只有被調用到才會裝載,從而實現了延遲加載

privatestaticclassSingletonHoder

//靜態初始化器,由JVM來保證線程安好

privatestaticGracefulSingletoninstance=newGracefulSingleton;

publicstaticGracefulSingletongetInstance

returnSingletonHoder.instance;

說一下我在實際開發中的場景:為了程序的高效率使用多線程并發,然而是循環調用,可能導致創造線程數過多,考慮采用線程池管理,這時候創造線程池依舊是處于循環調用中,也可能導致多個線程池,這時候就考慮使用單例模式。

源代碼:

publicclassThreadPoolFactoryUtil

privateExecutorServiceexecutorService;

//在構造函數中創造線程池

privateThreadPoolFactoryUtil

//獲取系統處理器個數,作為線程池數量

intnThreads=Runtime.getRuntime.availableProcessors;

executorService=Executors.newFixedThreadPoolnThreads;

//定義一個靜態內部類,內部定義靜態成員創造外部類實例

privatestaticclassSingletonContainer

privatestaticThreadPoolFactoryUtilutil=newThreadPoolFactoryUtil;

//獲取本類對象

publicstaticThreadPoolFactoryUtilgetUtil

returnSingletonContainer.util;

publicExecutorServicegetExecutorService

returnexecutorService;

涉及到一個靜態內部類,我們看看靜態內部類的特點:

1、靜態內部類無需憑借于外部類,它可以獨立于

溫馨提示

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

評論

0/150

提交評論