最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java中在多線程的情況下安全的修改list(常見解決方案)

 更新時(shí)間:2025年09月04日 09:27:39   作者:藤原とラふ店丶  
本文給大家介紹java中在多線程的情況下安全的修改list的常見解決方案及實(shí)現(xiàn)方式,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

在Java中,ArrayList、LinkedList等常見List實(shí)現(xiàn)類不是線程安全的(非同步)。當(dāng)多個(gè)線程同時(shí)對其進(jìn)行修改(如add、remove)或讀寫操作時(shí),可能會(huì)導(dǎo)致數(shù)據(jù)不一致、ConcurrentModificationException(并發(fā)修改異常)等問題。

要在多線程環(huán)境下安全地修改List,需通過線程安全的容器同步機(jī)制保證操作的原子性和可見性。以下是常用解決方案及實(shí)現(xiàn)方式:

一、使用線程安全的List實(shí)現(xiàn)類

Java提供了幾種線程安全的List實(shí)現(xiàn),可直接替換非線程安全的List,無需手動(dòng)處理同步。

1.Vector(古老實(shí)現(xiàn),不推薦)

Vector是Java早期的線程安全List實(shí)現(xiàn),其所有方法都被synchronized修飾(同步方法),保證線程安全。
缺點(diǎn):同步粒度太粗(整個(gè)方法加鎖),多線程并發(fā)效率低,且功能上被更優(yōu)的方案替代,不推薦在新代碼中使用

// Vector是線程安全的,但性能較差
List<String> vector = new Vector<>();
// 多線程可安全調(diào)用add/remove等方法
vector.add("A");
vector.remove(0);

2.Collections.synchronizedList()(包裝同步,推薦基礎(chǔ)場景)

Collections工具類的synchronizedList()方法可將任意非線程安全的List包裝為線程安全的List。其原理是對所有方法添加同步鎖(使用synchronized塊),保證同一時(shí)刻只有一個(gè)線程能操作List。

使用方式

// 1. 創(chuàng)建非線程安全的List(如ArrayList)
List<String> unsafeList = new ArrayList<>();
// 2. 包裝為線程安全的List
List<String> safeList = Collections.synchronizedList(unsafeList);
// 多線程環(huán)境下可安全操作
// 線程1:添加元素
new Thread(() -> {
    safeList.add("A");
}).start();
// 線程2:刪除元素
new Thread(() -> {
    if (!safeList.isEmpty()) {
        safeList.remove(0);
    }
}).start();

注意事項(xiàng)

迭代操作需手動(dòng)加鎖:synchronizedList返回的List在迭代時(shí)(如for-each、iterator不自動(dòng)同步,需手動(dòng)用synchronized塊包裹,否則可能拋出ConcurrentModificationException。

// 迭代時(shí)必須手動(dòng)同步(鎖對象為safeList本身)
synchronized (safeList) {
    for (String s : safeList) {
        System.out.println(s);
    }
}

適合讀寫頻率均衡的場景:由于所有操作都加鎖,高并發(fā)下性能一般,但實(shí)現(xiàn)簡單,適合大多數(shù)基礎(chǔ)場景。

3.CopyOnWriteArrayList(寫時(shí)復(fù)制,推薦讀多寫少場景)

CopyOnWriteArrayList是Java并發(fā)包(java.util.concurrent)提供的線程安全List,其核心原理是**“寫時(shí)復(fù)制”**:

  • 讀操作:無需加鎖,直接訪問當(dāng)前數(shù)組(性能極高)。
  • 寫操作(addremove等):先復(fù)制一份新的數(shù)組,在新數(shù)組上修改,然后將引用指向新數(shù)組(修改時(shí)加鎖,保證原子性)。

適用場景:讀操作遠(yuǎn)多于寫操作(如緩存、配置列表),寫操作頻率低但讀操作需高效。

使用方式

import java.util.concurrent.CopyOnWriteArrayList;
// 初始化線程安全的CopyOnWriteArrayList
List<String> cowList = new CopyOnWriteArrayList<>();
// 多線程安全操作
// 線程1:添加元素(寫操作,會(huì)復(fù)制數(shù)組)
new Thread(() -> {
    cowList.add("A");
}).start();
// 線程2:讀取元素(讀操作,無鎖,直接訪問)
new Thread(() -> {
    for (String s : cowList) {
        System.out.println(s);
    }
}).start();

優(yōu)點(diǎn)

  • 讀操作無鎖,并發(fā)性能極佳(適合讀多寫少)。
  • 迭代時(shí)不會(huì)拋出ConcurrentModificationException(迭代的是舊數(shù)組的快照)。

缺點(diǎn)

  • 寫操作成本高(復(fù)制數(shù)組,內(nèi)存占用翻倍)。
  • 數(shù)據(jù)實(shí)時(shí)性差(讀操作可能訪問的是舊數(shù)組,修改后的數(shù)據(jù)需等新數(shù)組替換后才能被讀?。?。

二、手動(dòng)同步(鎖機(jī)制)

如果需要更靈活地控制同步粒度(如僅對關(guān)鍵修改操作加鎖),可使用synchronized關(guān)鍵字或Lock接口手動(dòng)實(shí)現(xiàn)同步。

1. 使用synchronized塊

通過synchronized鎖定List對象或其他鎖對象,保證同一時(shí)刻只有一個(gè)線程執(zhí)行修改操作。

List<String> list = new ArrayList<>();
// 定義鎖對象(也可直接用list本身作為鎖)
Object lock = new Object();
// 線程1:添加元素
new Thread(() -> {
    synchronized (lock) { // 加鎖
        list.add("A");
    }
}).start();
// 線程2:刪除元素
new Thread(() -> {
    synchronized (lock) { // 加鎖
        if (!list.isEmpty()) {
            list.remove(0);
        }
    }
}).start();

2. 使用ReentrantLock(可重入鎖)

java.util.concurrent.locks.ReentrantLock提供比synchronized更靈活的鎖控制(如超時(shí)鎖、公平鎖),適合復(fù)雜場景。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
List<String> list = new ArrayList<>();
// 創(chuàng)建鎖對象(可指定為公平鎖,按請求順序獲取鎖)
Lock lock = new ReentrantLock(true);
// 線程1:添加元素
new Thread(() -> {
    lock.lock(); // 加鎖
    try {
        list.add("A");
    } finally {
        lock.unlock(); // 必須在finally中釋放鎖,避免死鎖
    }
}).start();
// 線程2:刪除元素
new Thread(() -> {
    lock.lock(); // 加鎖
    try {
        if (!list.isEmpty()) {
            list.remove(0);
        }
    } finally {
        lock.unlock();
    }
}).start();

三、注意事項(xiàng)

  • 復(fù)合操作的原子性
    • 即使使用線程安全的List,復(fù)合操作(如“先判斷再修改”)仍需額外同步。例如:
// 錯(cuò)誤示例:contains和add是兩個(gè)獨(dú)立操作,可能被其他線程打斷
if (!safeList.contains("A")) { 
    safeList.add("A"); // 可能重復(fù)添加
}
// 正確:用同步塊保證復(fù)合操作原子性
synchronized (safeList) {
    if (!safeList.contains("A")) {
        safeList.add("A");
    }
}
  • 迭代器的線程安全
    • synchronizedList的迭代器需手動(dòng)同步(見上文)。
    • CopyOnWriteArrayList的迭代器是“快照迭代器”,不支持remove、add等修改操作(會(huì)拋UnsupportedOperationException),只能遍歷。
  • 性能權(quán)衡
    • 讀多寫少:優(yōu)先CopyOnWriteArrayList(讀無鎖)。
    • 讀寫均衡或?qū)懖僮黝l繁:優(yōu)先Collections.synchronizedList()或手動(dòng)鎖(避免CopyOnWriteArrayList的復(fù)制開銷)。
    • 避免使用Vector(性能差,已過時(shí))。

總結(jié)

多線程安全修改List的核心是保證操作的原子性和可見性,常用方案對比:

方案原理優(yōu)點(diǎn)缺點(diǎn)適用場景
Vector同步方法簡單直接性能差,同步粒度粗兼容舊代碼(不推薦新用)
synchronizedList同步塊包裝適配所有List,實(shí)現(xiàn)簡單所有操作加鎖,并發(fā)性能一般讀寫均衡的基礎(chǔ)場景
CopyOnWriteArrayList寫時(shí)復(fù)制讀操作無鎖,性能極佳寫操作成本高,數(shù)據(jù)實(shí)時(shí)性差讀多寫少(如緩存、配置)
手動(dòng)鎖(synchronized/Lock自定義同步粒度靈活控制鎖范圍需手動(dòng)處理鎖釋放,易出錯(cuò)復(fù)雜場景(如復(fù)合操作)

根據(jù)實(shí)際業(yè)務(wù)的讀寫頻率和復(fù)雜度選擇合適方案即可。

到此這篇關(guān)于java中在多線程的情況下安全的修改list(常見解決方案)的文章就介紹到這了,更多相關(guān)java多線程修改list內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳細(xì)分析java并發(fā)之volatile關(guān)鍵字

    詳細(xì)分析java并發(fā)之volatile關(guān)鍵字

    這篇文章主要介紹了java并發(fā)之volatile關(guān)鍵字的的相關(guān)資料,文中代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • HttpClient詳細(xì)使用示例代碼

    HttpClient詳細(xì)使用示例代碼

    這篇文章主要介紹了HttpClient詳細(xì)使用示例,包括導(dǎo)入依賴,使用工具類的詳細(xì)代碼,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • SpringBoot實(shí)現(xiàn)其他普通類調(diào)用Spring管理的Service,dao等bean

    SpringBoot實(shí)現(xiàn)其他普通類調(diào)用Spring管理的Service,dao等bean

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)其他普通類調(diào)用Spring管理的Service,dao等bean,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java 批量文件壓縮導(dǎo)出并下載到本地示例代碼

    Java 批量文件壓縮導(dǎo)出并下載到本地示例代碼

    這篇文章主要介紹了Java 批量文件壓縮導(dǎo)出并下載到本地示例代碼,實(shí)現(xiàn)思路首先要把zip流寫入到http響應(yīng)輸出流中,再把excel的流寫入zip流中,具體示例代碼,大家通過本文學(xué)習(xí)吧
    2017-12-12
  • java中Arthas的作用和使用方式

    java中Arthas的作用和使用方式

    Arthas 是由阿里巴巴開源的 Java 診斷工具,主要用于在生產(chǎn)環(huán)境中診斷和解決 Java 應(yīng)用問題,它提供實(shí)時(shí)監(jiān)控、類信息查看、動(dòng)態(tài)追蹤、條件表達(dá)式斷點(diǎn)等功能,支持非侵入式設(shè)計(jì)和高擴(kuò)展性,通過 Arthas,開發(fā)者可以在不停止應(yīng)用的情況下,快速定位和解決問題
    2025-01-01
  • Spring Boot 之HelloWorld開發(fā)案例

    Spring Boot 之HelloWorld開發(fā)案例

    這篇文章主要介紹了Spring Boot 之HelloWorld開發(fā)案例,需要的朋友可以參考下
    2017-04-04
  • IntelliJ IDEA快速查看某個(gè)類/接口的子類或父類

    IntelliJ IDEA快速查看某個(gè)類/接口的子類或父類

    本文主要介紹了IntelliJ IDEA快速查看某個(gè)類/接口的子類或父類,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • DUCC配置平臺(tái)實(shí)現(xiàn)一個(gè)動(dòng)態(tài)化線程池示例代碼

    DUCC配置平臺(tái)實(shí)現(xiàn)一個(gè)動(dòng)態(tài)化線程池示例代碼

    這篇文章主要為大家介紹了DUCC配置平臺(tái)實(shí)現(xiàn)一個(gè)動(dòng)態(tài)化線程池示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Java 中限制方法的返回時(shí)間最新方法

    Java 中限制方法的返回時(shí)間最新方法

    最近在研究 ChatGPT 的 API 調(diào)用,因?yàn)?nbsp;ChatGPT 的 API 調(diào)用時(shí)間通常超過 30 秒,所以我們希望在程序中限制這個(gè)方法的執(zhí)行時(shí)間,不要讓方法花太長時(shí)間去執(zhí)行了,今天通過本文給大家分享Java 中如何限制方法的返回時(shí)間,感興趣的朋友跟隨小編一起看看吧
    2023-05-05
  • Java序列化常見的三個(gè)問題

    Java序列化常見的三個(gè)問題

    這篇文章主要介紹了Java序列化常見的三個(gè)問題,幫助大家更好的理解和學(xué)習(xí)JAVA,感興趣的朋友可以了解下
    2020-08-08

最新評論

富源县| 平顺县| 沙坪坝区| 舟山市| 台中市| 呼和浩特市| 日土县| 枞阳县| 沂水县| 田阳县| 荆门市| 如皋市| 长丰县| 偃师市| 尤溪县| 东平县| 龙江县| 循化| 梧州市| 茶陵县| 五河县| 托克逊县| 临沧市| 怀集县| 闽侯县| 盖州市| 祥云县| 万州区| 寿光市| 连江县| 白朗县| 赣州市| 方正县| 迭部县| 红河县| 夏邑县| 乌鲁木齐市| 绥德县| 佛山市| 临朐县| 金平|