? ?單例模式槐脏,也叫單一實(shí)例,其實(shí)就是為了保證一個類有且只有一個實(shí)例撇寞,并且為客戶端其他訪問提供一個全局的訪問點(diǎn)而設(shè)計(jì)的一種模式顿天。單例模式有多種實(shí)現(xiàn)實(shí)現(xiàn)方式堂氯,一般常見的有餓漢式單例、懶漢式單例牌废,然后其它方式基本都是針對這些單例模式進(jìn)行優(yōu)化咽白。
所謂單例,就是要控制只有一個實(shí)例畔规,要只有一個實(shí)例局扶,首先就要控制創(chuàng)建實(shí)例的地方,也就是說不能任何地方可以創(chuàng)建實(shí)例叁扫;舉個例子三妈,創(chuàng)建單例類,那么我們就可以將這個類的構(gòu)造方法private莫绣,只有自己才能創(chuàng)建畴蒲,然后再提供一個統(tǒng)一的創(chuàng)建實(shí)例入口就可以了,單例的基本原理就是這樣了对室。來模燥,上代碼:
一、懶漢模式
所謂懶漢掩宜,懶其實(shí)就是只有去對象時才創(chuàng)建對象蔫骂,創(chuàng)建完之后,就存在全局變量牺汤,后面再來取的就可以取值了辽旋。
二、餓漢模式
餓漢式檐迟,其實(shí)就是跟懶漢相反补胚,在類加載時就已經(jīng)創(chuàng)建了實(shí)體了,每次調(diào)用訪問接口追迟,直接取值就可以了溶其。
以上方式就以最簡單、最常見實(shí)現(xiàn)了單例模式敦间。但是瓶逃,還沒完美,怎么說呢每瞒?懶漢式創(chuàng)建金闽,如果在多線程里面,就極易產(chǎn)生問題剿骨,多個線程,同時判判為空埠褪,進(jìn)入創(chuàng)建對象浓利,那么這個對象變成了多線程里后創(chuàng)建的對象挤庇。那么如何優(yōu)化?可以在懶漢模式的方法中加一個synchronized鎖贷掖,如
這樣也就保證了多線程情況下嫡秕,對象唯一。哪么問題來了苹威,唯一保證了昆咽,但是高并發(fā)多線程情況下,讀取方法時都加鎖牙甫,加大程度下降低了效率掷酗。因此稍坯,加下還可以優(yōu)化:雙重檢查鎖漓穿;如
這樣既可以保證了單例,延遲了加載對象俗孝,也提高了效率且轨。這樣是不是很完美了浮声?不。這不是最理想的單例模式旋奢。synchronized通常稱為重量級鎖泳挥,而volatile是Java提供的一種輕量級的同步機(jī)制,簡稱輕量級鎖至朗。一定程度上會屏蔽虛擬機(jī)對代碼的優(yōu)化屉符,降低了虛擬機(jī)的執(zhí)行效率,因此如何優(yōu)化呢爽丹?這里引入一個內(nèi)部類實(shí)例生成方法筑煮。來上代碼:
當(dāng)?shù)谝淮卧L問內(nèi)部類時 ,虛擬機(jī)控制了內(nèi)部類靜態(tài)方法實(shí)例的生成粤蝎,保證了實(shí)例的唯一真仲,既可以不加鎖,也可以延長加載實(shí)例初澎,這才是完美做法秸应。