什么是JUC

摘要

Java并發工具包JUC是JDK5.0引入的重要并發編程工具,提供了更高級、靈活的并發控制機制。JUC包含鎖與同步器(如ReentrantLock、Semaphore等)、線程安全隊列(BlockingQueue)、原子變量(AtomicInteger等)、并發集合(ConcurrentHashMap)和線程池(ThreadPoolExecutor)等核心組件。相比傳統的synchronized關鍵字,JUC提供了更細粒度的控制、更好的性能和更豐富的功能。文章通過計數器實現、線程同步控制等實例展示了JUC組件的使用方法,并提醒開發者注意死鎖、內存一致性等潛在問題。JUC大大簡化了并發編程的復雜度,是Java高性能并發應用的重要基石。

什么是 JUC?

定義與背景

java.util.concurrent 是 JDK 5.0 引入的一個新包,旨在為開發者提供更高級別的并發編程支持。在此之前,Java 程序員主要依賴于 synchronized 關鍵字和 wait()/notify() 方法來實現線程同步和通信,這種方式雖然簡單但不夠靈活且容易出錯。JUC 包則引入了許多新的機制和技術,如鎖、信號量、線程池等,大大提升了并發程序的設計效率和可靠性。

核心理念

JUC 的設計遵循了幾個重要的原則:

  • 抽象層次高:提供了比原始鎖和條件變量更高層次的抽象,使得并發編程更加直觀。
  • 性能優化:內部實現了多種高效算法,例如自旋鎖、CAS 操作等,以減少上下文切換帶來的開銷。
  • 易用性強:封裝了大量的復雜邏輯,讓用戶可以專注于業務邏輯而不必擔心底層細節。
  • 可擴展性好:允許用戶根據需要定制化行為,如定義自己的線程工廠或拒絕策略。

JUC 的主要組成部分

JUC 包含了多個子模塊,每個模塊都針對特定類型的并發問題提供了相應的解決方案。以下是其中一些關鍵部分:

鎖與同步器

  • ReentrantLock:一個可重入的互斥鎖,提供了比內置鎖 (synchronized) 更豐富的功能,如嘗試獲取鎖、定時等待鎖等。
  • ReentrantReadWriteLock:讀寫分離的鎖,允許多個讀者同時訪問資源,但在寫操作時會阻塞所有其他線程。
  • Semaphore:信號量用于控制對共享資源的訪問數量,適用于限流場景。
  • CountDownLatchCyclicBarrier:前者用于一個或多個線程等待其他線程完成某些操作;后者則是讓一組線程相互等待直到滿足某個條件再繼續執行。

隊列

  • BlockingQueue:支持阻塞插入和移除元素的隊列接口,常用于生產者-消費者模式。
  • ConcurrentLinkedQueueConcurrentLinkedDeque:無鎖的線程安全隊列,適合高并發場景下的快速吞吐需求。
  • DelayQueue:只有當元素延遲到期后才能被取出的隊列,可用于任務調度。

原子變量

  • AtomicInteger, AtomicLong, AtomicBoolean 等:提供了一組原子操作的方法,保證了在多線程環境下的安全性而無需額外加鎖。
  • AtomicReference:對引用類型進行原子更新的支持。

并發集合

  • ConcurrentHashMap:高性能的哈希表實現,支持并發讀寫操作。
  • CopyOnWriteArrayListCopyOnWriteArraySet:基于快照機制的集合,讀取時不加鎖,寫入時創建新副本。

線程池

  • Executors:用于創建不同類型的線程池,如固定大小、緩存式、定時任務專用等。
  • ThreadPoolExecutor:線程池的核心實現類,允許自定義線程工廠、拒絕策略等。

實戰演練

接下來我們將通過幾個實際的例子來展示如何使用 JUC 包中的組件解決常見的并發問題。

使用 ReentrantLock 替代 synchronized

假設我們有一個計數器類,希望它能夠在多線程環境下正確地遞增。傳統方法可能會使用 synchronized 關鍵字:

public class Counter {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
}

然而,如果我們想增加更多的靈活性,比如設置超時時間或者嘗試非阻塞地獲取鎖,那么就可以考慮使用 ReentrantLock

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Counter {private int count = 0;private final Lock lock = new ReentrantLock();public void increment() {lock.lock();try {count++;} finally {lock.unlock();}}public int getCount() {lock.lock();try {return count;} finally {lock.unlock();}}
}

這段代碼中,ReentrantLock 提供了更多細粒度的操作選項,同時也保持了原有的線程安全性。

利用 CountDownLatch 實現線程同步

有時候我們需要確保某些線程必須等到其他線程完成了特定的工作才能繼續執行。例如,在啟動多個異步任務之前,主線程可能需要等待所有準備工作都已完成。這時可以使用 CountDownLatch 來實現:

import java.util.concurrent.CountDownLatch;public class Example {public static void main(String[] args) throws InterruptedException {int numThreads = 3;CountDownLatch startSignal = new CountDownLatch(1);CountDownLatch doneSignal = new CountDownLatch(numThreads);for (int i = 0; i < numThreads; ++i) {new Thread(new Worker(startSignal, doneSignal)).start();}// 讓工作線程準備好System.out.println("Main thread is ready.");startSignal.countDown();  // 向工作線程發出開始信號// 等待所有工作線程完成doneSignal.await();System.out.println("All threads have finished.");}static class Worker implements Runnable {private final CountDownLatch startSignal;private final CountDownLatch doneSignal;Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {this.startSignal = startSignal;this.doneSignal = doneSignal;}@Overridepublic void run() {try {startSignal.await();  // 等待開始信號doWork();doneSignal.countDown();  // 完成后通知主調方} catch (InterruptedException e) {Thread.currentThread().interrupt();}}private void doWork() {// 模擬工作System.out.println(Thread.currentThread().getName() + " is working...");try {Thread.sleep(1000);  // 模擬耗時操作} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}
}

在這個例子中,CountDownLatch 被用來協調主線程和工作線程之間的同步關系,確保所有準備工作完成后才真正啟動任務。

使用 ConcurrentHashMap 替換 HashMap

當我們需要在一個多線程環境中頻繁讀寫 Map 結構的數據時,ConcurrentHashMap 可以提供更好的性能和線程安全性:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;public class Example {private static final Map<String, String> map = new ConcurrentHashMap<>();public static void main(String[] args) {// 添加數據map.put("key1", "value1");map.putIfAbsent("key2", "value2");// 讀取數據String value = map.get("key1");// 更新數據map.computeIfPresent("key1", (k, v) -> "newValue");// 刪除數據map.remove("key2");// 遍歷數據map.forEach((k, v) -> System.out.println(k + "=" + v));}
}

ConcurrentHashMap 內部采用了分段鎖技術,只對涉及修改的部分進行鎖定,從而提高了并發訪問的效率。

注意事項

盡管 JUC 包提供了很多便利的功能,但在實際應用中也需要注意一些潛在的問題:

  • 死鎖風險:不當使用鎖可能導致死鎖現象,因此應該盡量避免嵌套鎖,并遵守一致的加鎖順序。
  • 內存一致性錯誤:即使使用了線程安全的數據結構,也不能忽視可見性和有序性的保證。必要時可以借助 volatile 關鍵字或原子變量。
  • 性能瓶頸:過多的同步操作可能成為系統的性能瓶頸,所以要權衡好線程安全性和執行效率之間的關系。
  • 異常處理:任何時候都不要忽略對異常情況的處理,尤其是在并發環境中,未捕獲的異常可能會導致不可預測的行為。

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

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

相關文章

零基礎學后端-PHP語言(第二期-PHP基礎語法)(通過php內置服務器運行php文件)

經過上期的配置&#xff0c;我們已經有了php的開發環境&#xff0c;編輯器我們繼續使用VScode&#xff0c;如果是新來的朋友可以看這期文章來配置VScode 零基礎學前端-傳統前端開發&#xff08;第一期-開發軟件介紹與本系列目標&#xff09;&#xff08;VScode安裝教程&#x…

擴散模型逆向過程詳解:如何從噪聲中恢復數據?

在擴散模型中&#xff0c;逆向過程的目標是從噪聲數據逐步恢復出原始數據。本文將詳細解析逆向條件分布 q(zt?1∣zt,x)q(\mathbf{z}_{t-1} \mid \mathbf{z}_t, \mathbf{x})q(zt?1?∣zt?,x)的推導過程&#xff0c;揭示擴散模型如何通過高斯分布實現數據重建。1. 核心問題 在…

2025年7月份實時最新獲取地圖邊界數據方法,省市區縣街道多級聯動【文末附實時geoJson數據下載】

動態生成最新行政區劃 GeoJSON 數據并結合 ECharts 實現地圖下鉆功能 在開發基于地圖的數據可視化應用時&#xff0c;一個常見的挑戰是獲取準確且最新的行政區劃邊界數據&#xff08;GeoJSON&#xff09;。許多現有的在線資源可能數據陳舊&#xff0c;無法反映最新的行政區劃調…

Spark實現WorldCount執行流程圖

spark可以分區并行執行&#xff0c;同時并行執行也可以基于內存完成迭代代碼對于大部分spark程序來說都是以driver開始driver結束&#xff0c;中間都是executor分布式運行

編程與數學 03-002 計算機網絡 02_網絡體系結構與協議

編程與數學 03-002 計算機網絡 02_網絡體系結構與協議一、網絡體系結構的基本概念&#xff08;一&#xff09;分層體系結構的優點&#xff08;二&#xff09;協議、接口與服務的概念二、OSI參考模型&#xff08;一&#xff09;七層模型的層次劃分及功能&#xff08;二&#xff…

Flutter 提取圖像主色調 ColorScheme.fromImageProvider

從圖像中提取主色調&#xff0c;用于動態適配顏色主題或者界面顏色。之前在 Flutter 應用里一直用的 palette_generator 插件&#xff0c;可以分析圖像顏色&#xff0c;從中提取一系列主要的色調。最近發現這個谷歌官方的插件竟然不維護了&#xff0c;后續沒有更新計劃了。 查找…

51c自動駕駛~合集8

自己的原文哦~ https://blog.51cto.com/whaosoft/11618683 #Hierarchical BEV BEV進入定制化時代&#xff01;清華Hierarchical BEV&#xff1a;創新多模塊學習框架&#xff0c;無痛落地無縫量產&#xff01;? 論文思路 自動駕駛指通過傳感器計算設備、信息通信、自…

Excel——重復值處理

識別重復行的三種方法方法1&#xff1a;COUNTIF公式法在E2單元格輸入公式&#xff1a;COUNTIF($B$2:$B2,B2)>1下拉填充至所有數據行結果為TRUE的即為重復行&#xff08;會標出第二次及以后出現的重復項&#xff09;方法2&#xff1a;排序IF公式法按商機號排序&#xff08;數…

華普微Matter模塊HM-MT7201,打破智能家居生態孤島

隨著智能家居滲透率與認可度的持續提升&#xff0c;消費者對于智能家居的功能訴求正從具備聯網控制、遠程控制與語音遙控等基礎交互能力&#xff0c;升級為能通過單一的家居生態平臺APP無縫控制所有的品牌設備&#xff0c;從而實現真正意義上的統一調度。這種從“單一設備聯網控…

如何使用 minio 完成OceanBase社區版的歸檔和備份

自OceanBase社區版4.2.1BP7版本起&#xff0c;OceanBase的歸檔與備份功能開始兼容AWS S3及S3協議的對象存儲服務&#xff0c;因此&#xff0c;許多用戶選擇采用 MinIO 作為其備份存儲介質。因為 MinIO 兼容AWS S3云存儲服務接口&#xff0c;成為了一個輕便的服務選項。 本文將…

Nacos-服務注冊,服務發現(二)

Nacos健康檢查 兩種健康檢查機制 Nacos作為注冊中?, 需要感知服務的健康狀態, 才能為服務調??提供良好的服務。 Nacos 中提供了兩種健康檢查機制&#xff1a; 客?端主動上報機制&#xff1a; 客?端通過?跳上報?式告知服務端(nacos注冊中?)健康狀態, 默認?跳間隔5…

手寫PPO_clip(FrozenLake環境)

參考&#xff1a;白話PPO訓練 成功截圖 算法組件 四大部分 同A2C相比&#xff0c;PPO算法額外引入了一個old_actor_model. 在PPO的訓練中&#xff0c;首先使用old_actor_model與環境進行交互得到經驗&#xff0c;然后利用一批經驗優化actor_model&#xff0c;最后再將actor_m…

人形機器人指南(八)操作

八、環境交互與操作能力——人形機器人的“靈巧雙手”環境交互與操作能力是人形機器人區別于移動平臺的核心能力標志。通過仿生學設計的運動鏈與智能控制算法&#xff0c;機器人得以在非結構化環境中執行抓取、操縱、裝配等復雜任務。本章將系統解析機械臂運動學架構、靈巧手設…

管理 GitHub Pages 站點的自定義域(Windows)

管理 GitHub Pages 站點的自定義域(Windows) 你可以設置或更新某些 DNS 記錄和存儲庫設置,以將 GitHub Pages 站點的默認域指向自定義域。 誰可以使用此功能? GitHub Pages 在公共存儲庫中提供 GitHub Free 和 GitHub Free for organizations,在公共和私有存儲庫中提供 Gi…

【PCIe 總線及設備入門學習專欄 5.1.3 -- PCIe PERST# 時序要求】

文章目錄 Overview 什么是PERST# 第一條要求 術語解釋 要求含義 第二條要求 術語解釋 要求含義 Perst 示例說明 過程如下 總結 Overview 首先我們看下 PCIe x協議對 PERST 的要求: A component must enter the LTSSM Detect state within 20 rms of the end of Fundamental R…

圖像認知與OpenCV——圖像預處理

目錄 一、顏色加法 顏色加法 顏色加權加法 示例 二、顏色空間轉換 RGB轉Gray&#xff08;灰度&#xff09; RGB轉HSV HSV轉RGB 示例 三、灰度化 最大值法 平均值法 加權平均值法 四、圖像二值化處理 閾值法 反閾值法 截斷閾值法 低閾值零處理 超閾值法 OTSU…

Vue 3 組件通信全解析:從 Props 到 Pinia 的深入實踐

引言 Vue 3 作為現代前端框架的代表之一&#xff0c;以其靈活性和高效性受到開發者的廣泛喜愛。在 Vue 3 中&#xff0c;組件是構建用戶界面的核心單元&#xff0c;而組件之間的通信則是實現動態交互和數據流動的關鍵環節。無論是簡單的父子組件通信&#xff0c;還是復雜的跨組…

CodeBuddy IDE實戰:用AI全棧能力快速搭建課程表網頁

聲明&#xff1a;本文僅是實踐測評&#xff0c;并非廣告 1.前言 在數字化開發的浪潮中&#xff0c;工具的革新往往是效率躍遷的起點。騰訊云 CodeBuddy IDE 是 “全球首個產設研一體 AI 全棧開發平臺” &#xff0c;它不僅打破了產品、設計與研發的職能壁壘&#xff0c;更重新…

11. HTML 中 DOCTYPE 的作用

總結H5 的聲明HTML5 的 DOCTYPE 聲明 HTML5 中的 <!DOCTYPE html> 聲明用于告訴瀏覽器當前文檔使用的是 HTML5 的文檔類型。它必須是文檔中的第一行內容&#xff08;在任何 HTML 標簽之前&#xff09;&#xff0c;以確保瀏覽器能夠正確地解析和渲染頁面。DOCTYPE 的作用 …

Linux C 網絡基礎編程

基礎知識在進行網絡編程之前&#xff0c;我們需要簡單回顧一下計算機網絡五層模型的網絡層和傳輸層&#xff0c;這兩層在面向后端編程時用的最多。物理層和鏈路層過于底層&#xff0c;已經完全由內核協議棧實現&#xff0c;不再細述。這里假設讀者已經對計算機網絡有一個大致的…