Java并發容器詳解

1. JUC并發容器概述

Java集合容器框架主要有四大類別:List、Set、Queue、Map。常見的ArrayList、LinkedList、HashMap等容器都是非線程安全的。

Java提供了同步容器(如Vector、Hashtable、SynchronizedList)通過synchronized實現同步,但會削弱并發性,降低吞吐量。為解決性能問題,java.util.concurrent包提供了多種并發類容器。

2. CopyOnWriteArrayList

2.1 概述

  • 對應的非并發容器:ArrayList
  • 目標:代替Vector、synchronizedList
  • 原理:利用讀多寫少的特性,讀操作不加鎖,寫操作時先復制新集合,修改后替換舊引用,通過volatile保證可見性

2.2 應用場景

  1. 讀多寫少的場景:讀取頻率遠高于寫入頻率的緩存
  2. 不需要實時更新的數據:如日志緩沖批量寫入

2.3 基本使用

// 創建CopyOnWriteArrayList對象
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();// 添加元素
list.add("element1");
list.add("element2");// 設置元素(指定下標)
list.set(0, "newElement");// 獲取元素
String element = list.get(0);// 刪除元素
list.remove(0);
list.remove("element2");// 其他操作
boolean isEmpty = list.isEmpty();
boolean contains = list.contains("element1");
int size = list.size();
list.clear();

2.4 IP黑名單判定示例

public class CopyOnWriteArrayListDemo {private static CopyOnWriteArrayList<String> blacklist = new CopyOnWriteArrayList<>();// 模擬初始黑名單數據static {blacklist.add("192.168.1.1");blacklist.add("192.168.1.2");blacklist.add("192.168.1.3");}public static void main(String[] args) {// 模擬請求處理Runnable requestHandler = () -> {try {Thread.sleep(new Random().nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}String clientIP = "192.168.1." + new Random().nextInt(6);if (blacklist.contains(clientIP)) {System.out.println(Thread.currentThread().getName() + " IP " + clientIP + " 命中黑名單,拒絕訪問");return;}System.out.println(Thread.currentThread().getName() + " IP " + clientIP + " 允許訪問");};// 啟動多個請求線程for (int i = 1; i <= 5; i++) {new Thread(requestHandler, "請求-" + i).start();}// 黑名單更新線程new Thread(() -> {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}String newBlackIP = "192.168.1.4";blacklist.add(newBlackIP);System.out.println("系統更新: 添加新黑名單IP " + newBlackIP);}, "黑名單更新").start();}
}

2.5 實現原理

采用"寫時復制"機制:

  1. 寫操作時創建新數組,復制原始數組內容
  2. 在新數組上進行修改操作
  3. 將引用指向新數組,通過volatile保證可見性
  4. 讀操作直接訪問數組,無需加鎖

2.6 缺陷

  1. 內存消耗:寫操作需要拷貝數組,可能引發GC
  2. 數據一致性:不能保證實時一致性,只能保證最終一致性
  3. 性能問題:數據量大時寫操作代價高昂

2.7 Fail-Fast vs Fail-Safe機制

Fail-Fast機制
  • 特點:快速失敗,檢測到并發修改立即拋出ConcurrentModificationException
  • 實現:java.util包中的集合類(ArrayList、HashMap等)
  • 解決方案
    • 使用synchronized(不推薦,影響性能)
    • 使用CopyOnWriteArrayList(推薦)
Fail-Safe機制
  • 特點:安全失敗,在復制的集合上修改,不拋出異常
  • 實現:java.util.concurrent包中的集合類
  • 缺點
    • 數據非實時一致
    • 內存占用更高(需要復制)
    • 可能引起頻繁GC

3. ConcurrentHashMap

3.1 概述

  • 對應的非并發容器:HashMap
  • 目標:代替Hashtable、synchronizedMap,支持復合操作
  • 原理
    • JDK6:分段鎖機制
    • JDK8:CAS + synchronized

3.2 應用場景

  1. 共享數據的線程安全:多線程環境下的數據讀寫
  2. 緩存實現:高并發緩存數據結構

3.3 基本使用

// 創建ConcurrentHashMap對象
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();// 添加鍵值對
map.put("key1", 1);
map.put("key2", 2);// 批量添加
HashMap<String, Integer> tempMap = new HashMap<>();
tempMap.put("key3", 3);
tempMap.put("key4", 4);
map.putAll(tempMap);// 獲取值
Integer value = map.get("key1");// 特殊方法
map.putIfAbsent("key1", 100); // 不存在則put,返回null;存在返回當前值
map.remove("key1", 1); // 鍵值匹配才刪除
map.replace("key2", 2, 20); // 鍵值匹配才替換// 其他操作
boolean isEmpty = map.isEmpty();
int size = map.size();
Set<String> keys = map.keySet();
Collection<Integer> values = map.values();
map.clear();

3.4 單詞統計示例

public class ConcurrentHashMapDemo {private static ConcurrentHashMap<String, AtomicLong> wordCountMap = new ConcurrentHashMap<>();private static CountDownLatch latch = new CountDownLatch(3);private static String[] words = {"apple", "banana", "orange", "apple", "banana"};public static void main(String[] args) throws InterruptedException {Runnable counterTask = () -> {for (int i = 0; i < 5; i++) {String word = words[new Random().nextInt(words.length)];// 獲取當前計數,不存在則初始化AtomicLong count = wordCountMap.get(word);if (count == null) {AtomicLong newCount = new AtomicLong(0);count = wordCountMap.putIfAbsent(word, newCount);if (count == null) {count = newCount;}}// 增加計數count.incrementAndGet();System.out.println(Thread.currentThread().getName() + ": " + word + " 計數: " + count.get());}latch.countDown();};// 啟動多個計數線程for (int i = 1; i <= 3; i++) {new Thread(counterTask, "計數器-" + i).start();}latch.await();System.out.println("最終統計結果: " + wordCountMap);}
}

3.5 數據結構演進

HashTable結構
  • 全表鎖,性能低下
JDK1.7 ConcurrentHashMap
  • 結構:Segment數組 + HashEntry數組 + 鏈表
  • 機制:分段鎖,寫操作分散到不同段
JDK1.8+ ConcurrentHashMap
  • 結構:數組 + 鏈表 + 紅黑樹(同HashMap)
  • 機制:CAS + synchronized
  • 樹化條件
    • 鏈表節點數 ≥ 8(TREEIFY_THRESHOLD)
    • 數組長度 ≥ 64(MIN_TREEIFY_CAPACITY)

4. ConcurrentSkipListMap

4.1 概述

  • 對應的非并發容器:TreeMap
  • 特點:基于跳表實現的線程安全有序Map
  • 優勢:支持高并發有序訪問和區間查詢

4.2 跳表(Skip List)原理

跳表是基于有序鏈表的概率型數據結構,支持O(log n)時間復雜度的查找、插入、刪除操作。

跳表特性
  1. 多層鏈表結構組成
  2. 每層都是有序鏈表
  3. 最底層包含所有元素
  4. 高層元素必定在低層出現
  5. 節點包含兩個指針:同級下一個元素、下層相同值元素
跳表操作
  • 查找:從最高層開始,向右查找直到大于目標值,然后向下一層繼續
  • 插入
    1. 隨機確定插入層級K
    2. K大于當前層級時創建新層
    3. 申請新節點并調整指針

4.3 基本使用

public class ConcurrentSkipListMapDemo {public static void main(String[] args) {ConcurrentSkipListMap<Integer, String> skipListMap = new ConcurrentSkipListMap<>();// 添加元素(自動排序)skipListMap.put(3, "Value3");skipListMap.put(1, "Value1");skipListMap.put(4, "Value4");skipListMap.put(2, "Value2");// 獲取元素String value = skipListMap.get(2);System.out.println("Key=2的值: " + value);// 遍歷元素(有序)System.out.println("按順序遍歷:");for (Integer key : skipListMap.keySet()) {System.out.println(key + " : " + skipListMap.get(key));}// 范圍查詢System.out.println("Key在1-3之間的元素:");ConcurrentNavigableMap<Integer, String> subMap = skipListMap.subMap(1, true, 3, true);subMap.forEach((k, v) -> System.out.println(k + " : " + v));// 刪除元素String removedValue = skipListMap.remove(3);System.out.println("刪除的值: " + removedValue);}
}

5. 其他并發容器(部分不常用)

5.1 CopyOnWriteArraySet

  • 對應的非并發容器:HashSet
  • 原理:基于CopyOnWriteArrayList實現
  • 特點:使用addIfAbsent方法保證元素唯一性

5.2 并發Queue

  • ArrayBlockingQueue:數組實現的有界阻塞隊列
  • LinkedBlockingQueue:鏈表實現的可選有界隊列
  • ConcurrentLinkedQueue:高性能非阻塞隊列
  • PriorityBlockingQueue:支持優先級的無界阻塞隊列

5.3 并發Deque

  • ConcurrentLinkedDeque:并發雙端隊列
  • LinkedBlockingDeque:鏈表實現的雙端阻塞隊列

6. 性能考量與最佳實踐

6.1 性能影響因素

  1. 并發級別:根據實際并發訪問量選擇合適容器
  2. 讀寫比例:讀多寫少選CopyOnWrite,寫多選ConcurrentHashMap
  3. 數據量大小:大數據量考慮ConcurrentSkipListMap
  4. 一致性要求:強一致選Hashtable,弱一致選并發容器

6.2 最佳實踐

  1. 明確需求:根據業務場景選擇最合適的容器
  2. 性能測試:在實際負載下測試容器性能
  3. 監控GC:關注并發容器可能引起的內存和GC問題
  4. 避免過度設計:簡單場景使用簡單解決方案
// 容器選型決策示例
public class ContainerSelector {public static <K, V> Map<K, V> createMap(boolean needOrdering, int expectedSize, int concurrencyLevel) {if (needOrdering) {return new ConcurrentSkipListMap<>();} else if (expectedSize > 1000000 || concurrencyLevel > 100) {return new ConcurrentHashMap<>(expectedSize, 0.75f, concurrencyLevel);} else {return new ConcurrentHashMap<>();}}public static <E> List<E> createList(boolean readHeavy, int expectedSize) {if (readHeavy && expectedSize < 10000) {return new CopyOnWriteArrayList<>();} else {return Collections.synchronizedList(new ArrayList<>());}}
}

選型總結

場景特點推薦容器理由
鍵值對操作,高并發ConcurrentHashMap線程安全,性能優良
大數據量有序訪問ConcurrentSkipListMap跳表結構,高效增刪
讀多寫少,數據量小CopyOnWriteArrayList讀無鎖,寫時復制
強一致性要求Hashtable全表鎖,保證強一致

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93743.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93743.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93743.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SpringAI系列---【SpringA集成OllamaI如何先調用向量庫,再把查到的結果一起傳給大模型?】

SpringAI如何先調用向量庫&#xff0c;再把查到的結果一起傳給大模型&#xff1f; 1.引入pom <dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-ollama</artifactId></depend…

告別“測試滯后”:AI實時測試工具在敏捷開發中的落地經驗

告別“測試滯后”&#xff1a;AI實時測試工具在敏捷開發中的落地經驗 在敏捷開發的“快速迭代”節奏中&#xff0c;測試環節常常成為“拖后腿”的短板。某互聯網公司的敏捷團隊曾陷入這樣的循環&#xff1a;2周迭代周期中&#xff0c;開發用10天完成功能&#xff0c;留給測試的…

K8S-Pod資源對象

一、K8S架構與組件1、K8S架構k8s 總體架構采用了經典的 maste/slave 架構模式&#xff0c;分 master 節點和 worker 節點&#xff0c;節點可以是虛擬機也可以是物理機。K8S組件 master 節點組件Kube-apiserver 用于暴露 Kubernetes API&#xff0c;任何資源請求或調用操作都是通…

PyTorch API 5

文章目錄torch.compiler延伸閱讀torch.fft快速傅里葉變換輔助函數torch.func什么是可組合的函數變換&#xff1f;為什么需要可組合的函數變換&#xff1f;延伸閱讀torch.futurestorch.fx概述編寫轉換函數圖結構快速入門圖操作直接操作計算圖使用 replace_pattern() 進行子圖重寫…

基于決策樹模型的汽車價格預測分析

一、整體流程概覽這份代碼實現了一個完整的機器學習預測流程&#xff0c;核心目標是通過汽車的各項特征預測其價格。整體流程分為 6 個主要步驟&#xff1a;模擬生成汽車數據集&#xff08;含價格標簽&#xff09;數據預處理&#xff08;清洗、編碼、特征選擇&#xff09;探索性…

0基礎安卓逆向原理與實踐:第2章:編程基礎與工具鏈

第2章:編程基礎與工具鏈 2.1 Java編程基礎 2.1.1 Java語言特性 Java是安卓應用開發的主要語言,具有以下核心特性: mindmaproot((Java特性))面向對象封裝繼承多態抽象平臺無關字節碼JVM一次編譯到處運行內存管理自動垃圾回收堆棧管理引用類型安全性字節碼驗證安全管理器訪…

深入理解JVM內存結構:從字節碼執行到垃圾回收的全景解析

&#x1f9e0; 深入理解JVM內存結構&#xff1a;從字節碼執行到垃圾回收的全景解析 #JVM內存模型 #Java性能優化 #垃圾回收機制 #并發編程一、JVM內存結構全景圖二、線程共享區域詳解 2.1 堆&#xff08;Heap&#xff09;—— 對象生存的宇宙 存儲內容&#xff1a; 所有new創建…

用 C++ 構建高性能測試框架:從原型到生產實戰指南

用 C 構建高性能測試框架&#xff1a;從原型到生產實戰指南 ?C 測試框架的關鍵價值?&#xff1a;當你的測試需要每秒處理百萬級交易&#xff0c;微秒級延遲要求已成為常態時&#xff0c;Python GC 的暫停便是不可接受的奢侈。 本文將深入探討如何用 C 構建兼具靈活性和高性能…

【C語言16天強化訓練】從基礎入門到進階:Day 4

&#x1f525;個人主頁&#xff1a;艾莉絲努力練劍 ?專欄傳送門&#xff1a;《C語言》、《數據結構與算法》、C語言刷題12天IO強訓、LeetCode代碼強化刷題、洛谷刷題、C/C基礎知識知識強化補充、C/C干貨分享&學習過程記錄 &#x1f349;學習方向&#xff1a;C/C方向 ??人…

C語言:字符函數與字符串函數(1)

在編程的過程中&#xff0c;我們經常會遇到需要處理字符和字符串的情況&#xff0c;為了方便操作字符和字符串&#xff0c;C語言標準庫中提供了一系列庫函數&#xff0c;接下來我們就學習一下這些函數。 目錄 1. 字符分類函數 2. 字母轉換函數 3. strlen函數的使用和模擬實現…

數據結構與算法系列(大白話模式)小學生起點(一)

出身&#xff0c;并不重要 &#xff01;&#xff01;&#xff01;&#xff01;只要有恒心&#xff0c;有毅力&#xff0c;肯于付出與學習&#xff0c;皆會取得相應的成就&#xff01;天道酬勤&#xff0c;天行健&#xff0c;君子當自強不息&#xff01;道可道&#xff0c;非常道…

計算機視覺第一課opencv(二)保姆級教學

目錄 簡介 一、邊界填充 1.函數說明 2.案例分析 二、圖像運算 1.號運算 2.cv2.add()函數 3.圖像加權運算 三、閾值處理 四、圖像平滑處理 1.椒鹽噪聲 2.均值濾波&#xff08;Mean Filtering&#xff09; 3.方框濾波 4. 高斯濾波&#xff08;Gaussian Filtering&am…

DINOv3

一、摘要 https://arxiv.org/pdf/2508.10104 自監督學習有望消除對人工數據標注的需求&#xff0c;使模型能夠輕松擴展到大規模數據集和更大規模的架構。由于不針對特定任務或領域進行定制&#xff0c;這種訓練范式具有從各種來源學習視覺表示的潛力&#xff0c;能夠使用單一…

??pytest+yaml+allure接口自動化測試框架

高薪必備&#xff01;18K接口自動化測試框架落地全流程&#xff5c;零基礎到實戰通關前言# 自動化測試&#xff0c;是目前測試行業一項比較普遍的測試技術了&#xff0c;之前的以UI自動化測試為主&#xff0c;現在的以接口自動化測試為主&#xff0c;無論技術更迭&#xff0c;…

LeetCode每日一題,2025-8-20

統計全為1的正方形子矩陣 這題是正方形&#xff0c;比較簡單 暴力就是二維前綴和。 或者用dp&#xff0c;dp[i][j]表示以i&#xff0c;j為右下角的最大正方形的邊長&#xff0c;它由(i-1,j),(i,j-1),(i-1,j-1)三者共同決定&#xff0c;通過找規律可知&#xff0c;由三個的最小值…

在Excel啟動時直接打開多個Excel文件

如果我們這段時間每天都要打開幾個相同的Excel文件開展工作&#xff0c;可以把這幾個文件放到一個文件夾&#xff08;如果原來就在不同的文件夾&#xff0c;就把快捷方式放到同一個文件夾&#xff09;&#xff0c;然后在Excel選項中設置啟動時打開這個文件夾中的文件即可。注&a…

對象存儲 COS 端到端質量系列 —— 終端網絡診斷工具

背景 在COS終端SDK的眾多功能中&#xff0c;文件上傳功能的使用頗為頻繁。鑒于此&#xff0c;提升文件上傳的成功率便顯得至關重要。眾多導致上傳失敗的因素里&#xff0c;由網絡問題引發的故障無疑是其中影響上傳成功率的關鍵因素之一&#xff0c;同時也是最難以把控的要素。…

Flask高效數據庫操作指南

Flask-SQLAlchemy 數據庫操作關于Flask數據庫Flask中沒有指定使用的數據庫&#xff0c;可以自由選擇不管你是使用關系型數據庫&#xff0c;還是非關系型數據庫都可以&#xff0c;不像django提供了orm 數據庫抽象層&#xff0c;可以直接采用對象的方式操作數據庫。但是為了開發效…

Camera相機人臉識別系列專題分析之十九:MTK ISP6S平臺FDNode原生代碼

【關注我,后續持續新增專題博文,謝謝!!!】 上一篇我們講了: 這一篇我們開始講: 目錄 一、問題背景 二、MTK ISP6S平臺FDNodeImp.cpp 2.1:原生代碼

S32K3 的圖形化配置和EB配置mcal差異

32K3系列的圖形化配置工具&#xff08;如S32 Design Studio, S32DS&#xff09;與EB配置工具&#xff08;基于EB tresos Studio&#xff09;在配置MCAL&#xff08;Microcontroller Abstraction Layer&#xff09;時存在關鍵差異&#xff0c;主要體現在工具環境、配置流程、代碼…