国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

設計模式(2)之單例模式

2019-11-06 06:15:30
字體:
來源:轉載
供稿:網友

一、單例模式的定義

單例模式:確保只有一個類只有一個實例,并提供一個全局訪問點。 應用場景:線程池(threadpool)、緩存(cache)、對話框、處理偏好設置和注冊表(registry)的對象、日志對象、充當打印機、顯卡等設備的的驅動程序的對象。在這些對象中,只能有一個實例。 根據此單一實例產生的時機不同,可以將其劃分為懶漢式、餓漢式。

二、三種方式介紹

(1)懶漢式:

package SingleTon;/** * Created by L_kanglin on 2017/3/7. * 懶漢式,經典的寫法 */public class SingleTon { //靜態實例變量 PRivate static SingleTon instance; //私有化構造函數 private SingleTon(){ } //靜態public方法,向整個應用提供單例獲取方式 public static SingleTon getInstance(){ if(instance==null){ instance= new SingleTon(); } return instance; }}

其特點是延遲實例化,上述代碼中instance是一個靜態變量,如果instance是空的,表示還沒有創建實例,而如果它不存在時,我們就利用私有的構造器產生一個Singleton實例,并把它賦值給instance靜態變量中,此時我們發現,如果我們不需要它,它就永遠不會產生,這也就是延遲實例化。 而如果instance不為空,說明之前已經創建這個對象,我們直接跳到return語句,并將其返回。

缺點:當處于多線程環境中時,當兩個線程同時需要執行這段代碼時

SingleTon sing = SingleTon.getInstance();

getInstance()方法是靜態的,意味著它是一個類方法,所以可以在代碼的任何地方使用SingleTon.getInstance()訪問它。這和訪問全局變量一樣,然而當兩個線程同時執行上述代碼時,就會出現錯誤。

改進后的懶漢式的線程安全寫法: a、將getInstance()變成同步(synchronized)方法,多線程中的安全問題基本解決。

package SingleTon;/** * Created by L_kanglin on 2017/3/7. * 懶漢式,改進一,加同步 */public class SingleTon { //靜態實例變量 private static SingleTon instance; //私有化構造函數 private SingleTon(){ } //靜態public方法,向整個應用提供單例獲取方式 public static synchronized SingleTon getInstance(){ if(instance==null){ instance= new SingleTon(); } return instance; }}

通過增加synchronized關鍵字到getInstance()方法中,我們使每個線程在進入這個方法之前,要先等候別的線程離開該方法。也就是說,不會有兩個線程可以同時進入這個方法。 但同步的同時,也帶來了性能的降低,只有第一次執行這個方法時,才真正的需要同步,一旦設置好instance變量后,就不再需要同步這個方法了,之后的調用,都是一種性能的消耗。 b、使用雙重檢查鎖,首先檢查是否實例創建了,如果尚未創建,才進行“同步”,這樣一來,只有第一次會同步。

package SingleTon;/** * Created by L_kanglin on 2017/3/7. * 懶漢式,改進二,雙重檢查加鎖 */public class SingleTon { //靜態實例變量 private volatile static SingleTon instance; //私有化構造函數 private SingleTon(){ } //靜態public方法,向整個應用提供單例獲取方式 public static SingleTon getInstance(){ if(instance==null){ synchronized(SingleTon.class){ if(instance==null){ instance= new Singleton(); } } } return instance; }}

首先檢查實例,如果不存在,就進入了同步區塊,注意只有第一次執行這個部分,進入區塊后,再檢查一次,如果仍是null,才創建實例。 volatile關鍵字:當instance變量被初始化成SingleTon實例時,多個線程正確的處理instance變量。

(2)餓漢式:應用程序總是創建并使用單件實例,或者在創建和運行時方面的負擔不太重,比較急切的創建此單件。

public class SingleTon { //在靜態初始化器中創建單例,這段代碼保證了線程安全 private static SingleTon instance = new SingleTon(); //私有化構造函數 private SingleTon(){ } //直接返回已創建好的實例 public static SingleTon getInstance(){ return instance; }}

依賴JVM在加載這個類時馬上創建此唯一的單件實例。JVM保證在任何線程訪問instance靜態變量之前,一定先創建此實例。

三、分析

懶漢式比較懶,只有當調用的時候,才會去初始化這個單例;餓漢式就是這個類一旦被加載,就創建了單例,在getInstance時,此時已經存在了這個單例。 (1)線程安全 餓漢式是線程安全的,可直接用于多線程而不會出現問題。 懶漢始經典方式是線程不安全的,但通過同步和雙重檢查加鎖的機制,可以實現線程安全。

(2)資源的占用 懶漢式也就是延遲實例化,在第一次使用該對象時,才會實例化出來,如果要做的事情比較多,性能上會有些延遲。 餓漢式在創建的時候就實例化出來,會首先占用一定的內存,并且第一次調用它的時候,速度會很快,由于初始化的過程早已完成。

補充:插入某個評論 假設沒有關鍵字volatile的情況下,兩個線程A、B,都是第一次調用該單例方法,線程A先執行instance = new Instance(),該構造方法是一個非原子操作,編譯后生成多條字節碼指令,由于java的指令重排序,可能會先執行instance的賦值操作,該操作實際只是在內存中開辟一片存儲對象的區域后直接返回內存的引用,之后instance便不為空了,但是實際的初始化操作卻還沒有執行,如果就在此時線程B進入,就會看到一個不為空的但是不完整(沒有完成初始化)的Instance對象,所以需要加入volatile關鍵字,禁止指令重排序優化,從而安全的實現單例。

memory=allocate(); //1:分配對象的內存空間 ctorInstance(memory); //2:初始化對象 instance=memory; //3:設置instance指向剛分配的內存地址 上面3行代碼中的2和3之間,可能會被重排序導致先3后2,

文章只是作為自己的學習筆記,借鑒了網上的許多案例,如果覺得闊以的話,希望多交流,在此謝過…


上一篇:6.猜數字

下一篇:5.股票風險

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 定西市| 太仆寺旗| 大庆市| 紫云| 云梦县| 宁蒗| 静安区| 汶川县| 民丰县| 安国市| 桐梓县| 德州市| 富裕县| 兴隆县| 桐庐县| 岳普湖县| 句容市| 宁阳县| 乌鲁木齐县| 承德县| 革吉县| 榆中县| 台湾省| 大姚县| 青浦区| 河池市| 奉化市| 潢川县| 长海县| 孟连| 湄潭县| 康平县| 调兵山市| 迭部县| 平遥县| 呼玛县| 石景山区| 旬阳县| 贵定县| 茶陵县| 乌拉特前旗|