一文詳解Java線程安全的集合有哪些
Java 提供了多種線程安全的集合,它們位于 java.util.concurrent
包下,主要分為以下幾類:
1. 阻塞隊(duì)列 (BlockingQueue)
阻塞隊(duì)列是一種特殊的隊(duì)列,當(dāng)隊(duì)列為空時(shí),獲取元素的操作會(huì)被阻塞,直到隊(duì)列中有元素可用;當(dāng)隊(duì)列已滿時(shí),添加元素的操作會(huì)被阻塞,直到隊(duì)列中有空閑位置。
ArrayBlockingQueue
: 基于數(shù)組的有界阻塞隊(duì)列,按照 FIFO(先進(jìn)先出)原則對(duì)元素進(jìn)行排序。LinkedBlockingQueue
: 基于鏈表的可選有界阻塞隊(duì)列(默認(rèn)無界),按照 FIFO 原則對(duì)元素進(jìn)行排序。PriorityBlockingQueue
: 無界阻塞隊(duì)列,支持優(yōu)先級(jí)排序。SynchronousQueue
: 同步隊(duì)列,不存儲(chǔ)元素,每個(gè)插入操作必須等待另一個(gè)線程的移除操作,反之亦然。DelayQueue
: 無界阻塞隊(duì)列,只有在延遲期滿時(shí)才能從中提取元素。LinkedTransferQueue
: 一個(gè)由鏈表結(jié)構(gòu)組成的無界阻塞隊(duì)列,它在SynchronousQueue的基礎(chǔ)上添加了transfer方法。
代碼示例 (ArrayBlockingQueue):
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class BlockingQueueExample { public static void main(String[] args) throws InterruptedException { BlockingQueue<String> queue = new ArrayBlockingQueue<>(10); // 生產(chǎn)者線程 Thread producer = new Thread(() -> { try { for (int i = 0; i < 20; i++) { queue.put("Item " + i); // 如果隊(duì)列滿了,會(huì)阻塞 System.out.println("Produced: Item " + i); Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } }); // 消費(fèi)者線程 Thread consumer = new Thread(() -> { try { for (int i = 0; i < 20; i++) { String item = queue.take(); // 如果隊(duì)列為空,會(huì)阻塞 System.out.println("Consumed: " + item); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } }); producer.start(); consumer.start(); } }
2. 并發(fā) Map (ConcurrentMap)
ConcurrentMap
接口是 Map
接口的子接口,提供了線程安全的并發(fā)操作。
ConcurrentHashMap
: 基于哈希表的線程安全 Map 實(shí)現(xiàn),使用分段鎖(JDK 1.7)或 CAS + synchronized (JDK 1.8+) 來實(shí)現(xiàn)并發(fā)控制。ConcurrentSkipListMap
: 基于跳表 (Skip List) 的線程安全 Map 實(shí)現(xiàn),支持排序。
代碼示例 (ConcurrentHashMap):
import java.util.concurrent.ConcurrentHashMap; public class ConcurrentHashMapExample { public static void main(String[] args) { ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>(); // 多個(gè)線程并發(fā)地向 map 中添加元素 Runnable task = () -> { for (int i = 0; i < 1000; i++) { map.putIfAbsent("Key" + i, i); // 原子操作 } }; Thread thread1 = new Thread(task); Thread thread2 = new Thread(task); thread1.start(); thread2.start(); } }
3. 并發(fā) Set (ConcurrentSet)
ConcurrentSkipListSet
: 基于跳表的線程安全的Set,支持排序。CopyOnWriteArraySet
: 基于CopyOnWriteArrayList
實(shí)現(xiàn)的線程安全 Set。
4. 并發(fā) List (ConcurrentList)
CopyOnWriteArrayList
: 線程安全的 List 實(shí)現(xiàn),通過 寫時(shí)復(fù)制 (Copy-On-Write) 的方式來實(shí)現(xiàn)并發(fā)控制。每次修改操作都會(huì)創(chuàng)建一個(gè)新的數(shù)組副本,讀操作在原來的數(shù)組上進(jìn)行,因此讀操作不需要加鎖,可以并發(fā)進(jìn)行。適用于讀多寫少的場(chǎng)景。
代碼示例 (CopyOnWriteArrayList):
import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class CopyOnWriteArrayListExample { public static void main(String[] args) { List<String> list = new CopyOnWriteArrayList<>(); // 讀線程 Runnable reader = () -> { for (String item : list) { System.out.println("Read: " + item); } }; // 寫線程 Runnable writer = () -> { list.add("New Item"); System.out.println("Added: New Item"); }; } }
5. 其他
Collections.synchronizedXXX
方法:Collections
工具類提供了一些靜態(tài)方法,可以將非線程安全的集合包裝成線程安全的集合,例如:Collections.synchronizedList(List<T> list)
Collections.synchronizedSet(Set<T> s)
Collections.synchronizedMap(Map<K,V> m)
這些方法通過在每個(gè)方法上添加synchronized
關(guān)鍵字來實(shí)現(xiàn)線程安全,性能較低。
總結(jié):
Java 并發(fā)包提供了豐富的線程安全集合,可以滿足不同的并發(fā)編程需求。選擇合適的線程安全集合需要考慮以下因素:
- 數(shù)據(jù)結(jié)構(gòu): 數(shù)組、鏈表、哈希表、跳表等。
- 是否有界: 有界、無界。
- 排序: 是否需要排序。
- 讀寫比例: 讀多寫少、寫多讀少、讀寫均衡。
- 性能要求: 對(duì)并發(fā)性能的要求。
問題分析:
這個(gè)問題考察了 Java 中線程安全集合的種類和用法。
與其他問題的知識(shí)點(diǎn)聯(lián)系:
- Java 線程安全的集合有哪些? 這是對(duì) Java 并發(fā)集合的整體了解。
- Java 中的 synchronized 是怎么實(shí)現(xiàn)的?
Collections.synchronizedXXX
方法使用了synchronized
關(guān)鍵字。 - Java 中 ReentrantLock 的實(shí)現(xiàn)原理是什么? 一些并發(fā)集合(如
ArrayBlockingQueue
)內(nèi)部使用了ReentrantLock
。 - 什么是 Java 的 CAS(Compare-And-Swap)操作? 一些并發(fā)集合(如
ConcurrentHashMap
)使用了 CAS 操作。 - 你使用過 Java 中的哪些阻塞隊(duì)列? 阻塞隊(duì)列是線程安全集合的重要組成部分。
理解這些聯(lián)系可以幫助你更全面地掌握 Java 并發(fā)編程的知識(shí),并了解如何在實(shí)際應(yīng)用中選擇合適的線程安全集合。
到此這篇關(guān)于Java線程安全集合有哪些的文章就介紹到這了,更多相關(guān)Java線程安全的集合內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)現(xiàn)FutureTask的示例詳解
在并發(fā)編程當(dāng)中我們最常見的需求就是啟動(dòng)一個(gè)線程執(zhí)行一個(gè)函數(shù)去完成我們的需求,而在這種需求當(dāng)中,我們需要函數(shù)有返回值。Java給我們提供了這種機(jī)制,去實(shí)現(xiàn)這一個(gè)效果:FutureTask。本文為大家準(zhǔn)備了Java實(shí)現(xiàn)FutureTask的示例代碼,需要的可以參考一下2022-08-08mybatis自定義類型處理器TypehHandler示例詳解
我們?cè)趯憁apper映射器的配置文件時(shí),不經(jīng)意間已經(jīng)用到類型轉(zhuǎn)換,不過是mybatis幫我們完成的,下面這篇文章主要給大家介紹了關(guān)于mybatis自定義類型處理器TypehHandler的相關(guān)資料,需要的朋友可以參考下2018-09-09關(guān)于Spring中@Value注解使用和源碼分析
通過深入分析@Value注解的使用和源碼,本文詳細(xì)解釋了Spring如何解析@Value注解并為屬性賦值,首先,Spring會(huì)解析并收集所有被@Value注解修飾的屬性,這一過程依賴于AutowiredAnnotationBeanPostProcessor類2024-11-11Java實(shí)現(xiàn)簡(jiǎn)易生產(chǎn)者消費(fèi)者模型過程解析
這篇文章主要介紹了Java實(shí)現(xiàn)簡(jiǎn)易生產(chǎn)者消費(fèi)者模型過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06Springboot引入攔截器并放行swagger代碼實(shí)例
這篇文章主要介紹了Springboot引入攔截器并放行swagger代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11SpringBoot過濾敏感詞的兩種實(shí)現(xiàn)方式
Spring Boot本身并不直接提供過濾敏感詞的功能,但你可以使用第三方庫或者自定義過濾器來實(shí)現(xiàn)這個(gè)需求,所以本文給大家介紹了SpringBoot過濾敏感詞的兩種實(shí)現(xiàn)方式,感興趣的朋友可以參考下2024-06-06