Java多線程編程環境中單例模式的實現_第1頁
Java多線程編程環境中單例模式的實現_第2頁
Java多線程編程環境中單例模式的實現_第3頁
Java多線程編程環境中單例模式的實現_第4頁
Java多線程編程環境中單例模式的實現_第5頁
已閱讀5頁,還剩2頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

1、 Java代碼1public class Singleton23private static Singleton instance=new Singleton(;4private Singleton(567public static Singleton getInstance(8return instance;910這樣的代碼缺點是:第一次加載類的時候會連帶著創建Singleton實例,這樣的結果與我們所期望的不同,因為創建實例的時候可能并不是我們需要這個實例的時候。同時如果這個Singleton實例的創建非常消耗系統資源,而應用始終都沒有使用Singleton實例,那么創建Singleton

2、消耗的系統資源就被白白浪費了。為了避免這種情況,我們通常使用惰性加載的機制,也就是在使用的時候才去創建。以上代碼的惰性加載代碼如下: Java代碼11public class Singleton12private static Singleton instance=null;13private Singleton(141516public static Singleton getInstance(17if(instance=null18instance=new Singleton(;19return instance;2021這樣,當我們第一次調用Singleton.getInstance(的

3、時候,這個單例才被創建,而以后再次調用的時候僅僅返回這個單例就可以了。2惰性加載在多線程中的問題先將惰性加載的代碼提取出來: Java代碼22public static Singleton getInstance(23if(instance=null24instance=new Singleton(;25return instance;26這是如果兩個線程A和B同時執行了該方法,然后以如下方式執行:1.A進入if判斷,此時foo為null,因此進入if內2.B進入if判斷,此時A還沒有創建foo,因此foo也為null,因此B也進入if內3.A創建了一個Foo并返回4.B也創建了一個Foo并返

4、回此時問題出現了,我們的單例被創建了兩次,而這并不是我們所期望的。3各種解決方案及其存在的問題3.1使用Class鎖機制以上問題最直觀的解決辦法就是給getInstance方法加上一個synchronize前綴,這樣每次只允許一個線程調用getInstance方法: Java代碼27public static synchronized Singleton getInstance(28if(instance=null29instance=new Singleton(;30return instance;31這種解決辦法的確可以防止錯誤的出現,但是它卻很影響性能:每次調用getInstance方法

5、的時候都必須獲得Singleton的鎖,而實際上,當單例實例被創建以后,其后的請求沒有必要再使用互斥機制了3.2double-checked locking曾經有人為了解決以上問題,提出了double-checked locking的解決方案 Java代碼32public static Singleton getInstance(33if(instance=null34synchronized(instance35if(instance=null36instance=new Singleton(;3738return instance;39讓我們來看一下這個代碼是如何工作的:首先當一個線程發出

6、請求后,會先檢查instance是否為null,如果不是則直接返回其內容,這樣避免了進入synchronized塊所需要花費的資源。其次,即使第2節提到的情況發生了,兩個線程同時進入了第一個if判斷,那么他們也必須按照順序執行synchronized塊中的代碼,第一個進入代碼塊的線程會創建一個新的Singleton實例,而后續的線程則因為無法通過if判斷,而不會創建多余的實例。上述描述似乎已經解決了我們面臨的所有問題,但實際上,從JVM的角度講,這些代碼仍然可能發生錯誤。對于JVM而言,它執行的是一個個Java指令。在Java指令中創建對象和賦值操作是分開進行的,也就是說instance=ne

7、w Singleton(;語句是分兩步執行的。但是JVM并不保證這兩個操作的先后順序,也就是說有可能JVM會為新的Singleton實例分配空間,然后直接賦值給instance成員,然后再去初始化這個Singleton實例。這樣就使出錯成為了可能,我們仍然以A、B兩個線程為例:1.A、B線程同時進入了第一個if判斷2.A首先進入synchronized塊,由于instance為null,所以它執行instance=new Singleton(;3.由于JVM內部的優化機制,JVM先畫出了一些分配給Singleton實例的空白內存,并賦值給instance 成員(注意此時JVM沒有開始初始化這個

8、實例,然后A離開了synchronized塊。4.B進入synchronized塊,由于instance此時不是null,因此它馬上離開了synchronized塊并將結果返回給調用該方法的程序。5.此時B線程打算使用Singleton實例,卻發現它沒有被初始化,于是錯誤發生了。4通過內部類實現多線程環境中的單例模式為了實現慢加載,并且不希望每次調用getInstance時都必須互斥執行,最好并且最方便的解決辦法如下: Java代碼40public class Singleton41private Singleton(424344private static class SingletonContainer45private static Singleton instance=new Singleton(;4647public static Singleton getInstance(48return SingletonContainer.instance;4950JVM內部的機制能夠保證當一個類被加載的時候,這個類的加載過程是線程互斥的。這樣當我們第一次調用getInstance的時候,JVM能夠幫我們保證instance只被創建一次,并且會保證把賦值給instance的內存初始化完畢,這樣我們就不用擔心3.2中的問

溫馨提示

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

評論

0/150

提交評論