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

Java如何解決ArrayList的并發(fā)問題

 更新時(shí)間:2025年04月30日 09:44:30   作者:Roc.Chang  
這篇文章主要介紹了Java如何解決ArrayList的并發(fā)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

ArrayListjava.util包中的一個(gè)類,它不是線程安全的。

如果多個(gè)線程同時(shí)對(duì)同一個(gè)ArrayList進(jìn)行操作,可能會(huì)導(dǎo)致并發(fā)問題,如數(shù)據(jù)不一致ConcurrentModificationException異常。

1. 場(chǎng)景復(fù)現(xiàn)

1.1 數(shù)據(jù)不一致問題示例代碼

import java.util.ArrayList;
import java.util.List;

public class ArrayListConcurrencyExample {
    public static void main(String[] args) {
        List<Integer> arrayList = new ArrayList<>();

        // 創(chuàng)建并啟動(dòng)多個(gè)線程,同時(shí)向ArrayList添加元素
        Runnable addTask = () -> {
            for (int i = 0; i < 1000; i++) {
                arrayList.add(i);
            }
        };

        Thread thread1 = new Thread(addTask);
        Thread thread2 = new Thread(addTask);

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 輸出ArrayList的大小,不一定是預(yù)期的 2000 
        System.out.println("Size of arrayList: " + arrayList.size());
    }
}

1.2 ConcurrentModificationException 問題示例代碼

ConcurrentModificationException通常會(huì)在迭代ArrayList(或其他集合)的同時(shí)對(duì)其進(jìn)行結(jié)構(gòu)性修改時(shí)拋出。

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

public class ConcurrentModificationExample {
    public static void main(String[] args) {
        List<String> arrayList = new ArrayList<>();

        arrayList.add("Item1");
        arrayList.add("Item2");
        arrayList.add("Item3");

        // 獲取迭代器
        Iterator<String> iterator = arrayList.iterator();

        // 開始迭代
        while (iterator.hasNext()) {
            String item = iterator.next();
            System.out.println(item);

            // 在迭代過程中嘗試修改ArrayList的結(jié)構(gòu),會(huì)引發(fā)ConcurrentModificationException
            if (item.equals("Item2")) {
                arrayList.remove(item);
            }
        }
    }
}

當(dāng)處理ArrayList的并發(fā)問題時(shí),不同的方法有不同的細(xì)節(jié)和適用場(chǎng)景。以下是對(duì)每種方法的詳細(xì)解釋:

2. 解決并發(fā)的三種方法

2.1 使用 Collections.synchronizedList

使用 Collections.synchronizedList 創(chuàng)建線程安全的ArrayList這是一種簡(jiǎn)單的方式來使ArrayList線程安全。

它實(shí)際上是包裝了一個(gè)原始的ArrayList,并在每個(gè)方法上添加synchronized關(guān)鍵字來確保每個(gè)方法在同一時(shí)間只能由一個(gè)線程訪問。

List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());

這種方法適用于那些多數(shù)情況下是讀操作,但偶爾需要寫操作的情況。

請(qǐng)注意,盡管每個(gè)方法都是線程安全的,但多個(gè)操作之間沒有原子性保證,因此還需要其他方式來確保多個(gè)操作的一致性。

例如下面的代碼就會(huì)出現(xiàn)并發(fā)問題:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SynchronizedListExample {
    public static void main(String[] args) {
        List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());

        Runnable addAndRemoveTask = () -> {
            for (int i = 0; i < 1000; i++) {
                synchronizedList.add(i);
                synchronizedList.remove(synchronizedList.size() - 1);
            }
        };

        Thread thread1 = new Thread(addAndRemoveTask);
        Thread thread2 = new Thread(addAndRemoveTask);

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Size of synchronizedList: " + synchronizedList.size());
    }
}

在這個(gè)示例中,兩個(gè)線程同時(shí)執(zhí)行addremove操作。雖然每個(gè)操作本身是線程安全的,但它們的組合會(huì)導(dǎo)致競(jìng)態(tài)條件,多次運(yùn)行后,會(huì)出現(xiàn)下面的情況:

最終列表的大小可能不是預(yù)期的 2000。

由于兩個(gè)線程同時(shí)進(jìn)行remove操作,可能導(dǎo)致其中一個(gè)線程試圖刪除一個(gè)元素,但在另一個(gè)線程之前已經(jīng)刪除了,導(dǎo)致IndexOutOfBoundsException異?;蚱渌灰恢碌慕Y(jié)果

Exception in thread "Thread-0" java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 1
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
    at java.base/java.util.Objects.checkIndex(Objects.java:372)
    at java.base/java.util.ArrayList.remove(ArrayList.java:536)
    at java.base/java.util.Collections$SynchronizedList.remove(Collections.java:2435)
    at com.test.testlist.SynchronizedListExample.lambda$main$0(SynchronizedListExample.java:14)
    at java.base/java.lang.Thread.run(Thread.java:834)
Size of synchronizedList: 1

這突顯了Collections.synchronizedList在某些情況下可能無法提供足夠的并發(fā)保護(hù),因此需要額外的同步措施或選擇更適合并發(fā)操作的數(shù)據(jù)結(jié)構(gòu)。

2.2 使用 CopyOnWriteArrayList(推薦使用)

CopyOnWriteArrayList是一種并發(fā)集合,它通過在寫操作時(shí)創(chuàng)建一個(gè)新的副本來解決并發(fā)問題。

這意味著讀操作不會(huì)受到寫操作的影響,而且不會(huì)拋出ConcurrentModificationException異常。

List<String> list = new CopyOnWriteArrayList<>();

這種方法適用于讀操作頻繁,寫操作較少的情況,因?yàn)閷懖僮鲿?huì)比較昂貴。但它非常適用于多線程下的讀操作,因?yàn)樗恍枰~外的同步。

2.3 使用顯式的同步控制

這種方法需要在需要修改ArrayList的地方使用synchronized塊或鎖來確保線程安全。

這是一種更精細(xì)的控制方法,適用于需要更多控制和協(xié)同操作的場(chǎng)景。

List<String> list = new ArrayList<>();

// 在需要修改list的地方加鎖
synchronized (list) {
    list.add("item");
}

這種方式要求手動(dòng)管理鎖,通過加鎖確保在修改ArrayList時(shí)進(jìn)行同步,以防止多個(gè)線程同時(shí)訪問它。

總結(jié)

  • 一般在日常編碼中,直接使用 CopyOnWriteArrayList 就能滿足很多場(chǎng)景;
  • 但是由于每次進(jìn)行寫操作時(shí),都需要復(fù)制整個(gè)列表,這會(huì)導(dǎo)致寫操作的性能較低,尤其在列表很大時(shí)。因此,CopyOnWriteArrayList 適用于讀操作頻繁、寫操作較少的場(chǎng)景。
  • 使用 CopyOnWriteArrayList 時(shí)候,應(yīng)該避免在迭代過程中修改列表;
  • CopyOnWriteArrayList 的迭代器具有弱一致性,在迭代過程中,迭代器可能無法反映出最新的修改,可能會(huì)遺漏或重復(fù)元素。如果非要強(qiáng)一致性,那就需要全局鎖或分布式鎖來處理了。
  • 大多數(shù)場(chǎng)景中,更多的還是讀多寫少;
  • 所以一般解決并發(fā)的方法,其實(shí)就是讓并發(fā)寫的操作,變成串行的;如果非要保證最終的強(qiáng)一致性,那肯定最終還是串行化處理,非常影響性能。
  • 如果是分布式系統(tǒng)的話,那肯定就要使用分布式鎖來處理了。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 在 Spring Boot 中集成 MinIO 對(duì)象存儲(chǔ)

    在 Spring Boot 中集成 MinIO 對(duì)象存儲(chǔ)

    MinIO 是一個(gè)開源的對(duì)象存儲(chǔ)服務(wù)器,專注于高性能、分布式和兼容S3 API的存儲(chǔ)解決方案,本文將介紹如何在 Spring Boot 應(yīng)用程序中集成 MinIO,以便您可以輕松地將對(duì)象存儲(chǔ)集成到您的應(yīng)用中,需要的朋友可以參考下
    2023-09-09
  • Spring Boot 整合 JWT的方法

    Spring Boot 整合 JWT的方法

    這篇文章主要介紹了Spring Boot 整合 JWT的方法,文中實(shí)例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Java?離線中文語音文字識(shí)別功能的實(shí)現(xiàn)代碼

    Java?離線中文語音文字識(shí)別功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Java?離線中文語音文字識(shí)別,本次使用springboot?+maven實(shí)現(xiàn),官方demo為springboot+gradle,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • RabbitMQ中的Connection和Channel信道詳解

    RabbitMQ中的Connection和Channel信道詳解

    這篇文章主要介紹了RabbitMQ中的Connection和Channel信道詳解,信道是建立在 Connection 之上的虛擬連接,RabbitMQ 處理的每條 AMQP 指令都是通過信道完成的,需要的朋友可以參考下
    2023-08-08
  • SpringBoot攔截器實(shí)現(xiàn)登錄攔截的示例代碼

    SpringBoot攔截器實(shí)現(xiàn)登錄攔截的示例代碼

    本文主要介紹了SpringBoot攔截器實(shí)現(xiàn)登錄攔截,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Struts2實(shí)現(xiàn)多文件上傳功能

    Struts2實(shí)現(xiàn)多文件上傳功能

    這篇文章主要為大家詳細(xì)介紹了Struts2實(shí)現(xiàn)多文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • java中刪除文件/文件夾的3種方法示例小結(jié)

    java中刪除文件/文件夾的3種方法示例小結(jié)

    這篇文章主要介紹了java中刪除文件/文件夾的3種方法示例小結(jié),第一種是通過io刪除文件,第二種是通過Files.walk刪除文件,第三種是通過 Files.walkFileTree刪除文件,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2023-10-10
  • Java 替換空格

    Java 替換空格

    本文主要介紹了Java中替換空格的方法。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • 解決Springboot不能自動(dòng)提交數(shù)據(jù)庫連接問題

    解決Springboot不能自動(dòng)提交數(shù)據(jù)庫連接問題

    在使用SSM框架開發(fā)時(shí),若在同一Service內(nèi)部方法間互相調(diào)用,直接使用this關(guān)鍵字會(huì)導(dǎo)致事務(wù)管理失效,從而引發(fā)如數(shù)據(jù)庫連接不足等問題,原因是通過this調(diào)用不會(huì)經(jīng)過Spring的代理,因此不會(huì)自動(dòng)進(jìn)行事務(wù)處理
    2024-09-09
  • SSH 框架簡(jiǎn)介

    SSH 框架簡(jiǎn)介

    SSH是 struts+spring+hibernate的一個(gè)集成框架,是目前較流行的一種web應(yīng)用程序開源框架。本文給大家詳細(xì)看一下組成SSH的這三個(gè)框架
    2017-09-09

最新評(píng)論

固安县| 托克托县| 德格县| 南岸区| 新余市| 渝北区| 六盘水市| 互助| 新余市| 徐州市| 高州市| 高青县| 灌云县| 喀喇| 稷山县| 乌苏市| 三都| 孟村| 化隆| 博爱县| 桃江县| 松原市| 寻甸| 东乌珠穆沁旗| 海林市| 博湖县| 铜陵市| 兴仁县| 波密县| 安国市| 德化县| 安阳市| 卓资县| 太湖县| 芦山县| 垣曲县| 鸡西市| 柘城县| 兴业县| 保定市| 定襄县|