国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
《Head First設(shè)計模式》閱讀筆記.第五章
1.單件(單態(tài),Singleton)模式部分

*有些對象我們只需要一個,比如說:線程池(threadpool)、緩存(cache)、對話框()、處理偏好設(shè)置的對象、處理注冊表(register)的對象、日志對象,以及充當(dāng)打印機、顯卡等設(shè)備的驅(qū)動程序?qū)ο蟆_@些對象只能有一個實例,如果出現(xiàn)多個實例就會導(dǎo)致程序的行為異常、資源使用過量,或者產(chǎn)生的結(jié)果不一致等等問題。

*單件模式與全局靜態(tài)變量的區(qū)別:
(1)使用全局靜態(tài)變量需要程序員之間的約定才能保證只有一個實例,而單件模式無需這樣的約定就可以確保只有一個實例被創(chuàng)建。
(2)靜態(tài)變量在程序一開始就被創(chuàng)建(這取決于JVM的實現(xiàn)),而單件模式只是在使用時才創(chuàng)建對象。如果這個被創(chuàng)建的對象非常消耗資源,而在程序運行的過程中沒有用到它,就會造成很大的浪費,這是靜態(tài)變量的缺點。

*在單態(tài)模式中,如果不需要這個實例,它就永遠(yuǎn)不會被創(chuàng)建。這就是“延遲實例化(Lazy Instance)”。

*單件模式的應(yīng)用場景之一是設(shè)置類對象,比如注冊表設(shè)置(Register Setting)對象。如果設(shè)置對象有多份拷貝,就會把設(shè)置搞得一團糟。

*單件常用來管理共享的資源,比如數(shù)據(jù)庫連接池或線程池。

單件(Singleton)模式:確保一個類只有一個實例,并提供一個全局訪問點。

*多線程會影響到單件模式,如果不對它進(jìn)行處理就會在單件模式下仍然創(chuàng)建多于一個實例。
解決這個問題有以下三種方式:
(1)使用同步。但是簡單地給創(chuàng)建實例方法(getInstance())增加synchronized修飾符雖然可以解決多線程的問題,但是導(dǎo)致每次調(diào)用都同步,而在靜態(tài)變量被設(shè)置之后,同步就是多余的了,因此,這降低了程序的效率。
在程序頻繁運行的地方增加同步可能會使效率降低100倍!因此要盡量避免使用同步,如果使用,就要盡量縮減需要同步的代碼。
方法如下:
Java代碼
  1. ------------   
  2. public class Singleton {   
  3.     private static Singleton instance;   
  4.        
  5.     private Singleton() {}   
  6.        
  7.     public synchronized static Singleton getInstance() {   
  8.         if (instance == null) {   
  9.             instance = new Singleton();   
  10.         }   
  11.         return instance;   
  12.     }   
  13. }   
  14. ------------  

(2)使用“急切(eagerly)”創(chuàng)建實例,也就是在生命靜態(tài)變量的時候就創(chuàng)建實例,而不是等到使用的時候再創(chuàng)建。該方式適用于程序總是需要創(chuàng)建和使用單件實例、程序在創(chuàng)建和運行時負(fù)擔(dān)不是太重、單件實例占用的資源較少的情況。
方法如下:
Java代碼
  1. ------------   
  2. public class Singleton {   
  3.     private static Singleton instance = new Singleton();   
  4.        
  5.     private Singleton() {}   
  6.        
  7.     public static Singleton getInstance() {   
  8.         return instance;   
  9.     }   
  10. }   
  11. ------------  

(3)在創(chuàng)建實例方法(getInstance())方法中使用“雙重檢查加鎖(Double-Checked Locking)”,這樣既保持了“延遲實例化(Lazy Instance)”,又保證只在第一次調(diào)用時同步。
方法如下:
Java代碼
  1. ------------   
  2. public class Singleton {   
  3.     private volatile static Singleton instance;   
  4.        
  5.     private Singleton() {}   
  6.        
  7.     public static Singleton getInstance() {   
  8.         if (instance == null) {   
  9.             synchronized (Singleton.class) {   
  10.                 if (instance == null) {   
  11.                     instance = new Singleton();   
  12.                 }   
  13.             }   
  14.         }   
  15.         return instance;   
  16.     }   
  17. }   
  18. ------------  

在這個方法里使用到了volatile這個關(guān)鍵字,下面對這個“關(guān)鍵的”關(guān)鍵字進(jìn)行說明:
Java語言規(guī)范指出,為了獲得最佳速度,允許線程保存共享成員變量的私有拷貝,而且只當(dāng)線程進(jìn)入和離開同步代碼塊時才與共享成員變量的原始值進(jìn)行對比。
而被volatile修飾的成員變量在線程中的私有拷貝每次被線程訪問時,都強迫從共享內(nèi)存中重讀該成員變量的值。而且,當(dāng)成員變量的私有拷貝發(fā)生變化時,強迫線程將變化值回寫到共享內(nèi)存。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值。
因此volatile關(guān)鍵字是使“雙重檢查加鎖(Double-Checked Locking)”有效的前提。
但是需要注意,在1.4及以前版本的JDK中,JVM對volatile關(guān)鍵字的實現(xiàn)會導(dǎo)致雙重檢查加鎖失效,所以這個方法只適用于1.5(包含)以后版本。

*以上對三種處理多線程方法的總結(jié)也就是“Sharpen Your Pencil”的解答。

*可以通過把一個類中的全部方法都定義為靜態(tài)方法的方式來達(dá)到和單件模式同樣的效果,但是由于類的初始化順序由JVM控制,所以可能導(dǎo)致與初始化順序有關(guān)的BUG,而這樣的BUG常常難于被發(fā)現(xiàn)。當(dāng)類的初始化比較簡單時,可以使用此方法。

*類加載器會破壞單件模式,因為不同的類加載器可以分別創(chuàng)建同一個單件的對象,單件對象就有了多個實例。解決辦法是:自行指定類加載器,并且指定同一個類加載器。

*在Java 1.2及以前版本中,垃圾收集器有一個BUG,會造成單件在沒有全局引用時,被當(dāng)做垃圾清理掉。在1.2以后的版本中,這個BUG已經(jīng)得到了修復(fù),因此不用擔(dān)心了。
如果使用的是1.2及以前的版本,可以建立一個單件注冊表(Register),從而避免單件被垃圾收集器回收。

*雖然單件模式不支持繼承,但在一個軟件中用到它的機會并不多,所以這個限制幾乎沒有影響。

*Java中實現(xiàn)單件(Singleton)模式需要私有的構(gòu)造器、一個靜態(tài)變量和一個靜態(tài)方法。

2.單件(Singleton)模式實例

第一種實現(xiàn):
Java代碼
  1. public class ThreadPool {   
  2.     private static ThreadPool instance;   
  3.   
  4.     private ThreadPool() {   
  5.     }   
  6.   
  7.     public synchronized static ThreadPool getInstance() {   
  8.         if (instance == null) {   
  9.             instance = new ThreadPool();   
  10.         }   
  11.         return instance;   
  12.     }   
  13. }  


第二種實現(xiàn):
Java代碼
  1. public class DBConnectionPool {   
  2.     private static DBConnectionPool instance = new DBConnectionPool();   
  3.   
  4.     private DBConnectionPool() {   
  5.     }   
  6.   
  7.     public static DBConnectionPool getInstance() {   
  8.         return instance;   
  9.     }   
  10. }  


第三種實現(xiàn)(適用于1.5及以后版本):
Java代碼
  1. public class LogFactory {   
  2.     private volatile static LogFactory instance;   
  3.   
  4.     private LogFactory() {   
  5.     }   
  6.   
  7.     public static LogFactory getInstance() {   
  8.         if (instance == null) {   
  9.             synchronized (LogFactory.class) {   
  10.                 if (instance == null) {   
  11.                     instance = new LogFactory();   
  12.                 }   
  13.             }   
  14.         }   
  15.         return instance;   
  16.     }   
  17. }  


--END--
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Java設(shè)計模式-之Singleton單例模式 - 設(shè)計模式
java幾種方式實現(xiàn)單例設(shè)計模式
怎樣實現(xiàn)線程安全的延遲初始化單例模式 ??
Java單例模式深入詳解
單例模式的七種寫法
GoF設(shè)計模式之五 Singleton- -
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服