1代芜、AtomicLong和LongAdder的區(qū)別燕雁,Atomic解決ABA問題
LongAdder更高效并發(fā)高的情況下性能更好窒所,內(nèi)部采用cell分段cas。參考
AtomicStampedReference內(nèi)部維護(hù)一個(gè)版本號(hào)來解決ABA問題磅轻。
2珍逸、synchronized修飾方法塊和修飾靜態(tài)方法,synchronized和volatile區(qū)別
synchronized修飾非靜態(tài)方法或者方法塊時(shí)聋溜,鎖定的是當(dāng)前的對(duì)象弄息。synchronized修飾靜態(tài)方法時(shí),鎖定的類的Class對(duì)象勤婚、即類鎖摹量。synchronized可以保證原子性和內(nèi)存可見性,volatile保證的是內(nèi)存可見性馒胆,防止cpu的內(nèi)存指令重排缨称。可見性是指讀取cpu的內(nèi)存緩存的值的時(shí)候都從主內(nèi)存用load命令重新讀祝迂,每次寫都寫到緩存后立即用store命令寫到主內(nèi)存睦尽。
3、final修飾的類不可被繼承型雳,修飾的方法不能重寫当凡,修飾的變量不能修改。引用類型如map list用final修改后不能重新初始化但是可以修改值纠俭,如果想使用不可變的map可以用Collections.unmodifiableMap().方法傳過來的值不想在方法中被修改沿量,可以用public void printx(final int x)。
4冤荆、ThreadLocal原理以及應(yīng)用場(chǎng)景
ThreadLocal內(nèi)部實(shí)現(xiàn)了ThreadLocalMap朴则,線程有一個(gè)threadLocals屬性引用當(dāng)前ThreadLocalMap,key為當(dāng)前ThreadLocal钓简,value為要存放的對(duì)象乌妒。
內(nèi)存泄漏:內(nèi)部使用的是弱引用汹想,當(dāng)調(diào)用set get remove方法的時(shí)候會(huì)被動(dòng)的清除value為null的,如果不在調(diào)用了方法就會(huì)回收不了就會(huì)造成內(nèi)存泄漏撤蚊,所以最好用完后自己remove刪除古掏。
應(yīng)用場(chǎng)景:在http請(qǐng)求中,如果需要多次使用HttpRequest里的東西原來都是逐層傳遞侦啸,考慮在Filter里把HttpRequest放到ThreadLocal槽唾,這樣可以在任何地方使用而不用傳到其他層,在filter使用完畢后remove即可匹中。
5、同步集合
ArrayList->Vector->CopyOnWriteArrayList
HashMap->HashTable->ConcurrentHashMap
HashSet->CopyOnWriteArraySet
TreeSet->ConcurrentSkipListSet
TreeMap->ConcurrentSkipListMap
6豪诲、CountDownLatch顶捷、CyclicBarrier和Semaphore區(qū)別聯(lián)系使用場(chǎng)景
CountDownLatch一個(gè)主線程等待其它線程,countDown方法不會(huì)阻塞而逝統(tǒng)一阻塞到await方法屎篱,只能使用一次服赎。CyclicBarrier是多個(gè)線程統(tǒng)一在調(diào)用await方法后阻塞,barrier滿足條件后統(tǒng)一放行交播,可以復(fù)用重虑。Semaphore類似于鑰匙,acquire方法申請(qǐng)秦士,release方法釋放缺厉。
場(chǎng)景:一群人在操場(chǎng)上分跑道測(cè)試成績(jī),Semaphore就是限制每一波的人數(shù)不能大于跑道數(shù)隧土,一個(gè)學(xué)生開始跑就申請(qǐng)一個(gè)跑道提针,結(jié)束就釋放一個(gè)跑道。CyclicBarrier就是讓大家都阻塞到開始的位置曹傀,當(dāng)跑道滿了統(tǒng)一開始跑辐脖。CountDownLatch就是等一波學(xué)生都跑完了,老師才能組織下一個(gè)活動(dòng)皆愉。
7嗜价、HashMap1.8的優(yōu)化點(diǎn)
鏈表長度大于8使用紅黑樹,查詢時(shí)間復(fù)雜度為O(logN)
Node結(jié)點(diǎn)會(huì)保存key的hashcode高位運(yùn)算以后的值幕庐,擴(kuò)容時(shí)不用重新計(jì)算久锥,直接取hash然后進(jìn)行位運(yùn)算
擴(kuò)容時(shí)鏈表從尾部插入,1.7從頭插入導(dǎo)致鏈表反轉(zhuǎn)多線程引發(fā)死循環(huán)异剥,1.8不會(huì)死循環(huán)但是會(huì)丟失數(shù)據(jù)
8奴拦、ConcurrentHashMap1.71.8區(qū)別
1.7采用Segment數(shù)組和HashEntry數(shù)組和鏈表,Segment繼承自ReentrantLock届吁,tryLock獲取鎖错妖,獲取不到就循環(huán)一個(gè)與處理器核數(shù)有關(guān)系的次數(shù)執(zhí)行tryLock绿鸣。
先采用不加鎖的方式,連續(xù)計(jì)算元素的個(gè)數(shù)暂氯,最多計(jì)算3次:1潮模、如果前后兩次計(jì)算結(jié)果相同,則說明計(jì)算出來的元素個(gè)數(shù)是準(zhǔn)確的痴施;2擎厢、如果前后兩次計(jì)算結(jié)果都不同,則給每個(gè)Segment進(jìn)行加鎖辣吃,再計(jì)算一次元素的個(gè)數(shù)动遭;
1.8采用Node數(shù)組、鏈表神得、紅黑樹厘惦,使用synchronized鎖鎖定Node。當(dāng)鏈表長度超過8需要轉(zhuǎn)換為紅黑樹時(shí)才會(huì)判斷當(dāng)前是否需要擴(kuò)容哩簿。擴(kuò)容時(shí)用CAS修改每個(gè)Node的標(biāo)示來實(shí)現(xiàn)多線程復(fù)制宵蕉,鏈表或紅黑樹都需要組裝好兩個(gè)鏈表,然后復(fù)制到對(duì)應(yīng)的位置节榜。
baseCount記錄元素的個(gè)數(shù)羡玛,如果CAS修改baseCount失敗,使用CAS記錄到CounterCell數(shù)組中宗苍,累加baseCount和CounterCell數(shù)組中的數(shù)量稼稿,即可得到元素的總個(gè)數(shù)