Java 进阶——单例模式
一、單例模式概念及特點
? ? ? ??Java中單例模式是一種常見的設計模式,單例模式分三種:懶漢式單例、餓漢式單例、登記式單例三種。
單例模式有一下特點:
? ? ? ? 1、單例類只能有一個實例。
2、單例類必須自己自己創建自己的唯一實例。
? ? ? ? 3、單例類必須給所有其他對象提供這一實例。
而這個特點正是我們構造單例模式的方法:
1)構造函數私有化;
2)創建一個自身的對象;
3)向外提供方法。
單例模式確保某個類只有一個實例,而且自行實例化并向整個系統提供這個實例。在計算機系統中,線程池、緩存、日志對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。這些應用都或多或少具有資源管理器的功能。每臺計算機可以有若干個打印機,但只能有一個Printer Spooler,以避免兩個打印作業同時輸出到打印機中。每臺計算機可以有若干通信端口,系統應當集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調用??傊?#xff0c;選擇單例模式就是為了避免不一致狀態,避免政出多頭。
正是由于這個特 點,單例對象通常作為程序中的存放配置信息的載體,因為它能保證其他對象讀到一致的信息。例如在某個服務器程序中,該服務器的配置信息可能存放在數據庫或 文件中,這些配置數據由某個單例對象統一讀取,服務進程中的其他對象如果要獲取這些配置信息,只需訪問該單例對象即可。這種方式極大地簡化了在復雜環境 下,尤其是多線程環境下的配置管理,但是隨著應用場景的不同,也可能帶來一些同步問題。
 
 
二、單例模式的舉例
1、餓漢方式的單例模式
[java]?view plaincopy
特點:線程安全 但效率比較低 ?一開始就要加載類new一個對象
 
 
2、懶漢方式的單例模式
[java]?view plaincopy
 特點:Singleton通過將構造方法限定為private避免了類在外部被實例化,在同一個虛擬機范圍內,Singleton的唯一實例只能通過getInstance()方法訪問。
 ? ? ? ? ? ?事實上,通過Java反射機制是能夠實例化構造方法為private的類的,那基本上會使所有的Java單例實現失效。此問題在此處不做討論,姑且掩耳盜鈴地認為反射機制不存在。
? ? ?但是以上懶漢式單例的實現沒有考慮線程安全問題,它是線程不安全的,并發環境下很可能出現多個Singleton實例,要實現線程安全,有以下三種方式,都是對getInstance這個方法改造,保證了懶漢式單例的線程安全,如果你第一次接觸單例模式,對線程安全不是很了解,可以先跳過下面這三小條,去看餓漢式單例,等看完后面再回頭考慮線程安全的問題:
 
 
3、登記式單例類
[java]?view plaincopy
餓漢式和懶漢式區別
從名字上來說,餓漢和懶漢,
餓漢就是類一旦加載,就把單例初始化完成,保證getInstance的時候,單例是已經存在的了,
而懶漢比較懶,只有當調用getInstance的時候,才回去初始化這個單例。
 
 
另外從以下兩點再區分以下這兩種方式:
1、線程安全:
 
 餓漢式天生就是線程安全的,可以直接用于多線程而不會出現問題,
懶漢式本身是非線程安全的,為了實現線程安全有幾種寫法,分別是上面的1、2、3,這三種實現在資源加載和性能方面有些區別。
 
 
2、資源加載和性能:
? ? ? ?餓漢式在類創建的同時就實例化一個靜態對象出來,不管之后會不會使用這個單例,都會占據一定的內存,但是相應的,在第一次調用時速度也會更快,因為其資源已經初始化完成;
? ? ? 而懶漢式顧名思義,會延遲加載,在第一次使用該單例的時候才會實例化對象出來,第一次調用時要做初始化,如果要做的工作比較多,性能上會有些延遲,之后就和餓漢式一樣了。
 
 
什么是線程安全?
? ? ? ? 如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。
? ? ? ?或者說:一個類或者程序所提供的接口對于線程來說是原子操作,或者多個線程之間的切換不會導致該接口的執行結果存在二義性,也就是說我們不用考慮同步的問題,那就是線程安全的。
總結
以上是生活随笔為你收集整理的Java 进阶——单例模式的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: RS232 RS422 RS485通讯原
 - 下一篇: Android在全球的市场份额跃居全球第