Java無(wú)狀態(tài)對(duì)象
對(duì)象就是數(shù)據(jù)及對(duì)數(shù)據(jù)操作的封裝, 對(duì)象所包含的數(shù)據(jù)稱為對(duì)象的狀態(tài)(State), 實(shí)例變量與靜態(tài)變量稱為狀態(tài)變量。
如果一個(gè)類的同一個(gè)實(shí)例被多個(gè)線程共享并不會(huì)使這些線程存儲(chǔ)共享的狀態(tài),那么該類的實(shí)例就稱為無(wú)狀態(tài)對(duì)象(Stateless Object). 反之如果一個(gè)類的實(shí)例被多個(gè)線程共享會(huì)使這些線程存在共享狀態(tài),那么 該類的實(shí)例稱為有狀態(tài)對(duì)象. 實(shí)際上無(wú)狀態(tài)對(duì)象就是不包含任何實(shí)例變量也不包含任何靜態(tài)變量的對(duì)象。
線程安全問(wèn)題的前提是多個(gè)線程存在共享的數(shù)據(jù),實(shí)現(xiàn)線程安全的一種辦法就是避免在多個(gè)線程之間共享數(shù)據(jù),使用無(wú)狀態(tài)對(duì)象就是這種方法。
不可變對(duì)象是指一經(jīng)創(chuàng)建它的狀態(tài)就保持不變的對(duì)象,不可變對(duì)象具有固有的線程安全性. 當(dāng)不可變對(duì)象現(xiàn)實(shí)實(shí)體的狀態(tài)發(fā)生變化時(shí),系統(tǒng)會(huì)創(chuàng)建一個(gè)新的不可變對(duì)象,就如String字符串對(duì)象. 一個(gè)不可變對(duì)象需要滿足以下條件:
1、類本身使用final修飾,防止通過(guò)創(chuàng)建子類來(lái)改變它的定義。
2、所有的字段都是final修飾的,final字段在創(chuàng)建對(duì)象時(shí)必須顯示初始化,不能被修改。
3、如果字段引用了其他狀態(tài)可變的對(duì)象(集合,數(shù)組),則這些字段必須是private私有的。
1、被建模對(duì)象的狀態(tài)變化不頻繁。
2、同時(shí)對(duì)一組相關(guān)數(shù)據(jù)進(jìn)行寫操作,可以應(yīng)用不可變對(duì)象,既可以保障原子性也可以避免鎖的使用。
3、使用不可變對(duì)象作為安全可靠的Map鍵, HashMap鍵值對(duì)的存儲(chǔ)位置與鍵的hashCode()有關(guān),如果鍵的內(nèi)部狀態(tài)發(fā)生了變化會(huì)導(dǎo)致鍵的哈希碼不同,可能會(huì)影響鍵值對(duì)的存儲(chǔ)位置. 如果HashMap的鍵是一個(gè)不可變對(duì)象,則hashCode()方法的返回值恒定,存儲(chǔ)位置是固定的。