寧國(guó)建設(shè)投資有限公司網(wǎng)站制作網(wǎng)站要花多少錢
文章目錄
- 1. java中 怎么確保一個(gè)集合不能被修改
- 2. 隊(duì)列和棧是什么 有什么區(qū)別
- 3. Java8開始的ConcurrentHashMap為什么舍棄了分段鎖
- 4. ConcurrentHashMap 和 Hashtable有什么區(qū)別
- 5. ReadWriteLock和StampeLock
1. java中 怎么確保一個(gè)集合不能被修改
Java 中可以使用 Collections 類的 unmodifiableXXX() 方法來(lái)確保一個(gè)集合不能被修改。其中,XXX 表示需要被轉(zhuǎn)換的集合類型,如 List、Set、Map 等。這些方法都返回指定集合的不可修改視圖。
例如,如果需要確保一個(gè) List 集合不能被修改,可以使用以下方法:
List<String> list = new ArrayList<>();
// 往集合中添加元素List<String> unmodifiableList = Collections.unmodifiableList(list);
// 將 List 轉(zhuǎn)換為不可修改的視圖unmodifiableList.add("element"); // 會(huì)拋出 UnsupportedOperationException 異常
在上述代碼中,將一個(gè) ArrayList 集合轉(zhuǎn)換為了不可修改的 List 視圖,并且嘗試向該視圖中添加新元素,此時(shí)會(huì)拋出 UnsupportedOperationException 異常。
需要注意的是,雖然通過 unmodifiableXXX() 方法返回的集合視圖可以防止對(duì)其進(jìn)行新增、移除、修改等操作,但實(shí)際上集合元素本身并沒有被修改,因此如果原始集合發(fā)生了變化,集合視圖也會(huì)發(fā)生變化。因此,需要確保不會(huì)通過其他方式來(lái)修改原集合。
2. 隊(duì)列和棧是什么 有什么區(qū)別
隊(duì)列和棧都是常見的數(shù)據(jù)結(jié)構(gòu),其主要區(qū)別在于元素的插入和刪除順序不同。
隊(duì)列(Queue)是一種先進(jìn)先出(First-In-First-Out,FIFO)的數(shù)據(jù)結(jié)構(gòu),類似于排隊(duì)等待服務(wù)。新元素總是被添加到隊(duì)列的尾部,而最先被添加的元素則總是位于隊(duì)列的頭部,也就是說,在隊(duì)列中,先進(jìn)入隊(duì)列的元素也會(huì)先被處理。我們可以通過調(diào)用隊(duì)列的 offer() 方法向隊(duì)列的尾部添加元素,可以通過 poll() 方法從隊(duì)列的頭部刪除元素。
棧(Stack)是一種后進(jìn)先出(Last-In-First-Out,LIFO)的數(shù)據(jù)結(jié)構(gòu),類似于疊羅漢。新元素總是被添加到棧的頂部,而最上面的元素則總是最后一個(gè)被處理,也就是說,在棧中,后進(jìn)入的元素先被處理。我們可以通過調(diào)用棧的 push() 方法向棧的頂部添加元素,可以通過 pop() 方法從棧的頂部刪除元素。
另外,還有一個(gè)明顯的區(qū)別是隊(duì)列允許在任何時(shí)候插入和刪除元素,而棧只能在棧頂進(jìn)行操作。此外,隊(duì)列通常有多種實(shí)現(xiàn)方式,如線性隊(duì)列、循環(huán)隊(duì)列和阻塞隊(duì)列等,每種實(shí)現(xiàn)方式都有其特點(diǎn)和適用場(chǎng)景;而棧的實(shí)現(xiàn)方式相對(duì)單一,大多數(shù)情況下只需要使用基本的數(shù)組或鏈表即可。
因此,當(dāng)需要處理一些按順序排列的元素集合時(shí),需要先進(jìn)先出的情況下就可以選擇使用隊(duì)列,如事件、消息等系統(tǒng);而對(duì)于需要依次處理?xiàng)m數(shù)那闆r,就可以使用棧,如表達(dá)式求值、函數(shù)調(diào)用等場(chǎng)景。
3. Java8開始的ConcurrentHashMap為什么舍棄了分段鎖
Java8開始的ConcurrentHashMap舍棄了分段鎖,主要是為了提高并發(fā)性能,這是因?yàn)樵诟卟l(fā)下使用分段鎖會(huì)出現(xiàn)一些缺點(diǎn)。
首先,基于分段鎖的 ConcurrentHashMap 在處理高并發(fā)場(chǎng)景時(shí)會(huì)出現(xiàn)頻繁的競(jìng)爭(zhēng),每當(dāng)有新元素插入到集合中或者需要進(jìn)行調(diào)整時(shí),需要加鎖來(lái)保證原子性,在競(jìng)爭(zhēng)激烈的情況下加鎖的開銷會(huì)顯得很大,阻礙整個(gè)系統(tǒng)的并發(fā)度。
其次,分段鎖本身也存在一些問題,例如需要維護(hù)多個(gè)鎖對(duì)象、容易產(chǎn)生死鎖等。雖然 JDK 7 中的 ConcurrentHashMap 引入了 Resize 的方式減少鎖的爭(zhēng)用,但在極端情況下仍然難以避免鎖引起的性能問題。
而在 Java8 中,ConcurrentHashMap 對(duì)底層數(shù)據(jù)結(jié)構(gòu)進(jìn)行了重構(gòu),在實(shí)現(xiàn)上使用了 CAS 操作(Compare And Swap,比較并交換)和內(nèi)存屏障等機(jī)制,可以實(shí)現(xiàn)更高效的非阻塞并發(fā)操作。這種方式在多線程訪問時(shí)避免了鎖的開銷,在性能表現(xiàn)上能夠更好地支持高并發(fā)訪問,相對(duì)于分段鎖提供了更好的性能和可擴(kuò)展性。
另外,在 Java8 中還引入了紅黑樹(Red-Black Tree)來(lái)代替鏈表,解決了 JDK 7 中并發(fā)度低且插入元素慢的問題,同時(shí)也讓每個(gè)線程擁有盡量少的鎖操作。這些改進(jìn)與優(yōu)化,都大大提升了 ConcurrentHashMap 的效率和性能表現(xiàn)。
4. ConcurrentHashMap 和 Hashtable有什么區(qū)別
ConcurrentHashMap 和 Hashtable 都是線程安全的集合類,它們之間有以下幾點(diǎn)區(qū)別:
同步方式不同
Hashtable 通過 synchronized 關(guān)鍵字來(lái)實(shí)現(xiàn)同步,對(duì)整個(gè)對(duì)象進(jìn)行鎖定,因此同一時(shí)刻只能有一個(gè)線程訪問該對(duì)象。而 ConcurrentHashMap 則通過分段鎖(JDK7及之前版本)或者無(wú)鎖算法(JDK8及以上版本)來(lái)實(shí)現(xiàn)同步,不同的線程可以同時(shí)訪問不同部分的數(shù)據(jù),因此并發(fā)度相對(duì)較高,性能也更好。
數(shù)據(jù)結(jié)構(gòu)不同
Hashtable 的數(shù)據(jù)結(jié)構(gòu)是數(shù)組加鏈表,當(dāng)一個(gè)鏈表中元素過多時(shí),會(huì)產(chǎn)生嚴(yán)重的時(shí)間復(fù)雜度優(yōu)化問題。ConcurrentHashMap在 JDK8 版本后引入紅黑樹來(lái)解決這個(gè)問題。
空值和空鍵的處理不同
Hashtable 不允許 null 值和 null 鍵,如果以 null 作為 key 或 value 的話則會(huì)拋出 NullPointerException。而 ConcurrentHashMap 允許 null 值和 null 鍵。
迭代器的弱一致性策略不同
當(dāng)其他獨(dú)立線程改變了 ConcurrentHashMap 集合中的某個(gè)數(shù)值時(shí),迭代器仍然可以繼續(xù)工作,而對(duì)于 Hashtable 則不能并發(fā)迭代,因?yàn)?iterators 在遍歷時(shí)要鎖定整個(gè)表格,所以將導(dǎo)致其他線程的所有訪問被阻塞。
ConcurrentHashMap 相對(duì)于 Hashtable 具有更好的并發(fā)性和可伸縮性,在高并發(fā)場(chǎng)景下,使用 ConcurrentHashMap 可以提供更優(yōu)秀的性能表現(xiàn)。
5. ReadWriteLock和StampeLock
ReadWriteLock和StampeLock都是Java并發(fā)包中提供的鎖機(jī)制,它們旨在優(yōu)化對(duì)于讀寫的并發(fā)操作。
ReadWriteLock
ReadWriteLock 接口定義了一個(gè)讀/寫鎖,它可以同時(shí)允許多個(gè)線程讀取共享資源,但只允許一個(gè)線程寫入共享資源,當(dāng)進(jìn)行寫鎖定時(shí),所有讀取線程和其他寫線程請(qǐng)求該鎖定將被阻塞。與一般的 Lock 實(shí)現(xiàn)不同的是,ReadWriteLock 允許多個(gè)線程同時(shí)訪問某個(gè)資源,以達(dá)到提高讀取操作性能的目的,在讀多寫少的場(chǎng)景下,使用 ReadWriteLock 可以有效減小鎖競(jìng)爭(zhēng),提高并發(fā)效率。
StampedLock
StampedLock 的實(shí)現(xiàn)基于樂觀鎖的思想,也是為了優(yōu)化讀操作執(zhí)行的速度而設(shè)計(jì)的一種鎖機(jī)制。由于讀取操作比寫操作更快,StampedLock 采用樂觀策略,當(dāng)進(jìn)行讀取操作時(shí),會(huì)嘗試樂觀獲取鎖,如果成功,則直接返回?cái)?shù)據(jù),否則就退化成傳統(tǒng)的悲觀鎖來(lái)獲取鎖。StampedLock 中也有三種模式:寫模式、悲觀讀模式和樂觀讀模式。StampedLock 支持可重入,并提供了將悲觀鎖降級(jí)為樂觀鎖的方法。
在讀多寫少的場(chǎng)景下,使用讀寫鎖(ReadWriteLock)或 StampedLock 可以取得很好的性能提升效果。但需要注意的是,并不是所有的場(chǎng)景都適合使用讀寫鎖或 StampedLock,在存在大量寫操作并且這些寫操作耗時(shí)很長(zhǎng)的情況下,這兩種鎖機(jī)制可能會(huì)導(dǎo)致讀操作被阻塞,進(jìn)而影響系統(tǒng)的響應(yīng)時(shí)間。