




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
實現(xiàn)一個具備不可變性的類,還是挺簡單的。將一個類所有的屬性都設置成nal的,并且只允許存在只讀方法,那么這個類基本上就具備不可變性了。更嚴格的做法是nal,也就是不允許繼承。因為子類可以覆蓋父類的方法,有可能改變不可變性,所以推薦你在實際工作中,使用這種更嚴格的做法。JaaK里很多類都具備不可變性,只是由于它們的使用太簡單,最后反而被忽略了。例如經(jīng)常用到的g和Intoube的、屬性和方法,你會發(fā)現(xiàn)它們都嚴格遵守不可變類的三點要求:類和屬性都是nal的,所有方法均是只讀的??吹竭@里你可能會疑惑,JavaString法也有類似字符替換操作,怎么能說所有方法都是只讀的呢?我們結(jié)合String的源代碼來解釋一下這個問題,下面的示例代碼源自Java1.8SDK,我略做了修改,僅保留了關鍵屬性value[]和rece()方法,你會發(fā)現(xiàn):String這個類以及它的屬性value[]都是final的;而rece()方法的實現(xiàn),就的確沒有修改value[],而是將替換后的字符串作為返回值返回了。代碼publicfinalclassStringprivatefinalchar//字符替Stringrece(charcharnewChar)//無需替換,直接返回if(oldChar==return intlen=inti=-/*avoidgetfieldopcodechar[]val=//定位到需要替換的字符位while(++i<len)if(val[i]==oldChar) //未找到oldChar,無需替if(i>=len)return //創(chuàng)建一個buf[],這是關//用來保存替換后的字charbuf[]=newfor(intj=0;j<i;j++)buf[j]= while(i<len)charc=buf[i]=(c==oldChar)newChar: //創(chuàng)建一個新的字符串//原字符串不會發(fā)生任何變returnnewString(buf, 41g創(chuàng)建一個新的不可變對象象的一個重要區(qū)別,可變對象往往是修改自己的屬性。Pattern)。利用享元模式可以減少創(chuàng)建對象的數(shù)量,從而減少內(nèi)存占用。Java里面Long、Integer、Short、Byte等這些基本數(shù)據(jù)類型的包裝類都用到了享元模式。下面我們就以Long這個類作為例子,看看它是如何利用享元模式來優(yōu)化對象的享元模式本質(zhì)上其實就是一個對象池,利用享元模式創(chuàng)建對象的邏輯也很簡單:創(chuàng)建之前,首先去對象池里看看是不是存在;如果已經(jīng)存在,就利用對象池里的對象;如果不存在,就會新創(chuàng)建一個對象,并且把這個新創(chuàng)建出來的對象放進對象池里。Long這個類并沒有照搬享元模式,Long內(nèi)部了一個靜態(tài)的對象池,僅緩存[-128,127]之間的數(shù)字,這個對象池在JVM啟動的時候就創(chuàng)建好了,而且這個對象池一都不會變化,也就是說它是靜態(tài)的。之所以采用這樣的設計,是因為Long這個對象的狀共有264種,實在太多,不宜全部緩存,而[-128,127]之間的數(shù)字利用率最高。下面的示例代碼出自Java1.8,valueOf()方法就用到了LongCache這個緩存,你可以結(jié)合著來加代碼LongvalueOf(longl)finalintoffset=//[-128,127]直接的數(shù)字做了緩if(l>=-128&&l<=127)return.cache[(int)l+ returnnew9//緩存,等價于對象//僅緩存[-128,127]直接的數(shù)staticclassLongCachestaticfinalLong=newLong[-(-128)+127+staticfor(inti=0;i<cache.length;cache[i]=newLong(i-}}前面我們在《13|理論基礎模塊熱點問題答疑》中提到“Integer和String類型的對象不模式,這會導致看上去私有的鎖,其實是共有的。例如在下面代碼中,本意是A用鎖al,B用鎖bl,各自管理各自的,互不影響。但實際上al和bl是一個對象,結(jié)果A和B共用代碼classALongpublicvoidsynchronized(al)//省略代碼無 8classBLongpublicsetBY(){synchronized(bl)//省略代碼無}}}使用Immutability在使用Immutability模式的時候,需要注意以對象的所有屬性都是final的,并不能保證不可變不可變對象也需要正確發(fā)Java言中,final飾的屬性一旦被賦值,就不可以再修改,但是如果屬性的類型是普通對象,那么這個普通對象的屬性是可以被修改的。例如下面的代碼中,Bar的屬性foo雖然是final的,依然可以通過setAge()方法來設置foo的屬性age。所以,在使用Immutability模式的時候一定要確認保持不變性的邊界在哪里,是否要求屬性對象也具備代碼classintint45finalclassBar6finalFoo7voidsetAge(int89}}著這些不可變對象的對象就是線程安全的。例如在下面的代碼中,F(xiàn)oo具備不可變性,線程安全,但是類Bar并不是線程安全的,類Bar中持有對Foo的foo,對這個的修改在多線程中并不能保證可見性和原子性代//Foo線程finalclassfinalintfinalint5//Bar線程不安classBar8Foo9voidsetFoo(Foo}}如果你的程序僅僅需要foo保持可見性,無需保證原子性,那么可以將foo為volatile變量,這樣就能保證可見性。如果你的程序需要保證原子性,那么可以通過原子類決了不可變對象的原子性問題。代碼publicclassSafeWMclassfinalintfinalintWMRange(intupper,int//省略構(gòu)造函數(shù)實} finalrf=newnew //設置庫存上voidsetUpper(intWMRangeor=//檢查參if(v<thrownew WMRangenr=WMRange(v, pareAndSet(or, 28利用Immutability模式解決并發(fā)問題,也許你覺得有點陌生,其實你天天都在享受它的戰(zhàn)果。Java語言里面的String和Long、Integer、Double等基礎類型的包裝類都具備不可變性,這些對象的線程安全性都是靠不可變性來保證的。Immutability模式是最簡單的解決并發(fā)問題的方法,建議當你試圖解決一個并發(fā)問題時,可以首先嘗試一下Immutability具備不變性的對象,只有一種狀態(tài),這個狀態(tài)由對象內(nèi)部所有的不變屬性共同決定。其實還有一種更簡單的不變性對象,那就是無狀態(tài)狀態(tài)的對象,你可能還聽無狀態(tài)的服務、無狀態(tài)的協(xié)議等等。無狀態(tài)有很多好處,最核心的一點就是性能。在多線程領域,無狀態(tài)對象沒有線程安全問題,無需同步處理,自然性能很好;在分布式領域,無狀態(tài)意味著可以無限地水平擴展,所以分布式領域里面性能的瓶頸一定不是出在無狀態(tài)的服務節(jié)點上。下面的示例代碼中,Account屬性是final,并且只有get法,那這個類是不是具代碼1publicfinalclass2private3StringBuffer4publicAccount(String5this.user6new7}89publicStringBufferreturn}publicStringreturn}} 科技所有 不 售賣。頁面已增加防盜追蹤,將依 其上一 27|并發(fā)工具類模塊熱點問題答下一 29|Copy-on-Write模式:不是延時策略的言精選留言言 18final讀的",類的屬性如果是型,該屬性對應的類也需要滿足不可變類的條件,且不能提供修改展張?zhí)?榣山樵客 4這段代碼應該是線程安全的,但它不是不可變模式。StringBuffer只是字段不可變,值展作者回復:對象正在輸 final 1//Foo線程安全 Foo{finalintfinalint展炎 展作者回復:感謝一路相伴 1不是不可變的,user展陳華 展 炎 staticclassLongCache{…展 finalStringBufferStingBuffer是類型,當我們說它finalStingBufferuser不可變時,實際上說的是它useruser對象,通過subappend展作者回復:易兒 publicfinalclassTestpublicstaticvoidmain(String[]args)Accoun
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- GB/T 45190-2025道地藥材生產(chǎn)技術規(guī)程岷當歸
- 文化創(chuàng)意產(chǎn)業(yè)項目研發(fā)投資合同
- 農(nóng)產(chǎn)品收購書合同
- 醫(yī)院裝修法律協(xié)議合同材料
- 外包項目勞動合同
- 全款二手房屋買賣合同書
- 焊接鋼管買賣合同
- 公司財務保密協(xié)議
- 三農(nóng)產(chǎn)品電子商務推廣應用方案
- 電子支付系統(tǒng)服務協(xié)議
- 新疆維吾爾自治區(qū)2024年中考英語真題【附真題答案】
- 繼續(xù)醫(yī)學教育項目申報表
- 《工程地質(zhì)學》孔憲立-石振明第五章(部編)課件
- 個人股份轉(zhuǎn)讓合同協(xié)議
- 供應商對比方案報告
- 兒童支氣管哮喘規(guī)范化診治建議(2020年版)
- ISO28000:2022供應鏈安全管理體系
- 臨床營養(yǎng)技術操作規(guī)范(2010版)
- 我國新零售業(yè)上市公司財務質(zhì)量分析-以蘇寧易購為例
- 華為中基層管理者任職資格評價標準樣本
- 富氫水完整課件
評論
0/150
提交評論