寫一個簡單的單例模式 單例設(shè)計模式惡漢和懶漢哪個線程安全?
單例設(shè)計模式惡漢和懶漢哪個線程安全?餓漢式獲取實例的步驟簡單所以線程更安全。懶漢式只是不會在類加載時即創(chuàng)建靜態(tài)對象而效率略高,而因此也導(dǎo)致有判斷是否已創(chuàng)建對象環(huán)節(jié)會使線程變得不安全,需要加同步鎖才能解
單例設(shè)計模式惡漢和懶漢哪個線程安全?
餓漢式獲取實例的步驟簡單所以線程更安全。懶漢式只是不會在類加載時即創(chuàng)建靜態(tài)對象而效率略高,而因此也導(dǎo)致有判斷是否已創(chuàng)建對象環(huán)節(jié)會使線程變得不安全,需要加同步鎖才能解決該問題。
單例模式中,餓漢式和懶漢式的區(qū)別?為什么推薦說,用餓漢模式?
單例中懶漢和餓漢的本質(zhì)區(qū)別在于以下幾點:
1、餓漢式是線程安全的,在類創(chuàng)建的同時就已經(jīng)創(chuàng)建好一個靜態(tài)的對象供系統(tǒng)使用,以后不在改變。懶漢式如果在創(chuàng)建實例對象時不加上synchronized則會導(dǎo)致對對象的訪問不是線程安全的。
2、從實現(xiàn)方式來講他們最大的區(qū)別就是懶漢式是延時加載,他是在需要的時候才創(chuàng)建對象,而餓漢式在虛擬機啟動的時候就會創(chuàng)建,餓漢式無需關(guān)注多線程問題,寫法簡單明了,能用則用。但是它是加載類時創(chuàng)建實例。所以如果是一個工廠模式,緩存了很多實例,那么就得考慮效率問題,因為這個類一加載則把所有實例不管用不用一塊創(chuàng)建。
3、兩者建立單例對象的時間不同。“懶漢式”是在你真正用到的時候才去建這個單例對象,“餓漢式”是在不管用不用得上,一開始就建立這個單例對象。擴展資料1、單例模式的優(yōu)點有:(1)實例控制:單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例。(2)靈活性:因為類控制了實例化過程,所以類可以靈活更改實例化過程。2、單例模式的缺點有:(1)開銷:雖然數(shù)量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,將仍然需要一些開銷。可以通過使用靜態(tài)初始化解決此問題。(2)可能的開發(fā)混淆:使用單例對象(尤其在類庫中定義的對象)時,開發(fā)人員必須記住自己不能使用new關(guān)鍵字實例化對象。因為可能無法訪問庫源代碼,因此應(yīng)用程序開發(fā)人員可能會意外發(fā)現(xiàn)自己無法直接實例化此類。
有人說設(shè)計模式是為了彌補Java語言的缺陷,你覺得是這樣嗎?
看你從哪個層面來看待設(shè)計模式!
語言層面
如果你從語言層面來看設(shè)計模式,那么這個說法可以說是對的。有部分設(shè)計模式是彌補了Java語言上的不足,最明顯的就是單例模式。
在Java中本身沒有提供單例對象的創(chuàng)建,需要通過單例模式來實現(xiàn),什么餓漢式,懶漢式,多線程下還要關(guān)注DCL,volatile關(guān)鍵字等等,衍生了很多的面試題。
而在現(xiàn)代語言中,很多都提供了創(chuàng)建單例對象的語法,比如Scala,Kotlin的object關(guān)鍵字。
代碼設(shè)計層面
如果從代碼設(shè)計層面來看,設(shè)計模式提供了一套可復(fù)用的代碼結(jié)構(gòu),來解決特定問題。比如,當(dāng)需要動態(tài)化某些可選部分時,可以使用策略模式。當(dāng)需要一組操作來順序操作某個對象時,可以使用職責(zé)鏈模式。
架構(gòu)層面
從架構(gòu)層面來看,設(shè)計模式對組件關(guān)系進(jìn)行了解耦。
假設(shè)我們要實現(xiàn)一個文件服務(wù)器,有一個UploadService來進(jìn)行上傳操作,可以調(diào)用ConvertService對文件進(jìn)行轉(zhuǎn)換。UploadService屬于核心模塊「上傳模塊」,而ConvertService屬于非核心模塊「轉(zhuǎn)換模塊」。
如果UploadService直接去調(diào)用ConvertService來執(zhí)行轉(zhuǎn)換,那么核心模塊就依賴了非核心模塊。如下圖:
非核心模塊是相對不穩(wěn)定的,核心模塊是相對穩(wěn)定的。核心模塊依賴了非核心模塊會導(dǎo)致核心模塊也不穩(wěn)定。所以可以使用策略模式來解耦:
看箭頭的方向,現(xiàn)在轉(zhuǎn)換模塊依賴于上傳模塊,轉(zhuǎn)換模塊的變化不會影響上傳模塊。依賴方向改變了,這就是傳說中的「依賴倒置」!