欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中CopyOnWriteArrayList的使用解析

 更新時間:2023年12月20日 08:47:50   作者:Yaaaaang194  
這篇文章主要介紹了Java中CopyOnWriteArrayList的使用解析,CopyOnWriteArrayList適合使用在讀操作遠遠大于寫操作的場景里,比如緩存,它不存在擴容的概念,每次寫操作都要復(fù)制一個副本,在副本的基礎(chǔ)上修改后改變Array引用,需要的朋友可以參考下

一、CopyOnWriteArrayList介紹

①、CopyOnWriteArrayList,寫數(shù)組的拷貝,支持高效率并發(fā)且是線程安全的,讀操作無鎖的ArrayList。所有可變操作都是通過對底層數(shù)組進行一次新的復(fù)制來實現(xiàn)。

②、CopyOnWriteArrayList適合使用在讀操作遠遠大于寫操作的場景里,比如緩存。它不存在擴容的概念,每次寫操作都要復(fù)制一個副本,在副本的基礎(chǔ)上修改后改變Array引用。CopyOnWriteArrayList中寫操作需要大面積復(fù)制數(shù)組,所以性能肯定很差。

③、CopyOnWriteArrayList 合適讀多寫少的場景,不過這類慎用 ,因為誰也沒法保證CopyOnWriteArrayList 到底要放置多少數(shù)據(jù),萬一數(shù)據(jù)稍微有點多,每次add/set都要重新復(fù)制數(shù)組,這個代價實在太高昂了。在高性能的互聯(lián)網(wǎng)應(yīng)用中,這種操作分分鐘引起故障。

二、CopyOnWriteArrayList 有幾個缺點

1、由于寫操作的時候,需要拷貝數(shù)組,會消耗內(nèi)存,如果原數(shù)組的內(nèi)容比較多的情況下,可能導(dǎo)致young gc或者full gc。 (1、young gc :年輕代(Young Generation):對象被創(chuàng)建時,內(nèi)存的分配首先發(fā)生在年輕代(大對象可以直接被創(chuàng)建在年老代),大部分的對象在創(chuàng)建后很快就不再使用,因此很快變得不可達,于是被年輕代的GC機制清理掉(IBM的研究表明,98%的對象都是很快消亡的),這個GC機制被稱為Minor GC或叫Young GC。

2、年老代(Old Generation):對象如果在年輕代存活了足夠長的時間而沒有被清理掉(即在幾次Young GC后存活了下來),則會被復(fù)制到年老代,年老代的空間一般比年輕代大,能存放更多的對象,在年老代上發(fā)生的GC次數(shù)也比年輕代少。當(dāng)年老代內(nèi)存不足時,將執(zhí)行Major GC,也叫 Full GC )

3、不能用于實時讀的場景,像拷貝數(shù)組、新增元素都需要時間,所以調(diào)用一個set操作后,讀取到數(shù)據(jù)可能還是舊的,雖然CopyOnWriteArrayList 能做到最終一致性,但是還是沒法滿足實時性要求;

三、CopyOnWriteArrayList的一些方法

1、add(E e) :將指定元素添加到此列表的尾部,返回值為boolean。

2、add(int index, E element) : 在此列表的指定位置上插入指定元素。

3、clear():從此列表移除所有元素。

4、contains(Object o) :如果此列表包含指定的元素,則返回 true。

5、equals(Object o) :比較指定對象與此列表的相等性。

6、get(int index) : 返回列表中指定位置的元素。
7、hashCode() : 返回此列表的哈希碼值。

8、indexOf(E e, int index) : 返回第一次出現(xiàn)的指定元素在此列表中的索引,從 index 開始向前搜索,如果沒有找到該元素,則返回 -1。

9、indexOf(Object o) :返回此列表中第一次出現(xiàn)的指定元素的索引;如果此列表不包含該元素,則返回 -1。

10、isEmpty() :如果此列表不包含任何元素,則返回 true。

11、iterator() :返回以恰當(dāng)順序在此列表元素上進行迭代的迭代器,返回值為 Iterator。

12、lastIndexOf(E e, int index) :返回最后一次出現(xiàn)的指定元素在此列表中的索引,從 index 開始向后搜索,如果沒有找到該元素,則返回 -1。

13、lastIndexOf(Object o) : 返回此列表中最后出現(xiàn)的指定元素的索引;如果列表不包含此元素,則返回 -1。

14、remove(int index) :移除此列表指定位置上的元素。

15、remove(Object o) :從此列表移除第一次出現(xiàn)的指定元素(如果存在),返回值為 boolean。

16、set(int index, E element) :用指定的元素替代此列表指定位置上的元素。

17、size() :返回此列表中的元素數(shù)。

18、subList(int fromIndex, int toIndex) :返回此列表中 fromIndex(包括)和 toIndex(不包括)之間部分的視圖,返回值為 List 。

四、Java代碼示例

package chapter3.copyonwrite;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
/**
 * @author czd
 */
public class CopyOnWriteArrayListTest {
    public static void main(String[] args) {
        /**
         * 構(gòu)造方法摘要
         * CopyOnWriteArrayList():
         *           創(chuàng)建一個空列表。
         * CopyOnWriteArrayList(Collection<? extends E> c):
         *           創(chuàng)建一個按 collection 的迭代器返回元素的順序包含指定 collection 元素的列表。
         * CopyOnWriteArrayList(E[] toCopyIn):
         *           創(chuàng)建一個保存給定數(shù)組的副本的列表。
         */
        /**
         * 1、add(E e) :將指定元素添加到此列表的尾部,返回值為boolean。
         *
         * 2、iterator() :返回以恰當(dāng)順序在此列表元素上進行迭代的迭代器,返回值為Iterator<E>。
         */
        CopyOnWriteArrayList<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
        Boolean addBoolean = copyOnWriteArrayList.add(1);
        System.out.println("是否添加到此列表的尾部?" + addBoolean);
        Iterator<Integer> iterator = copyOnWriteArrayList.iterator();
        while (iterator.hasNext()){
            System.out.println("iterator的結(jié)果: " + iterator.next());
        }
        /**
         * 3、add(int index, E element) :在此列表的指定位置上插入指定元素。
         */
        CopyOnWriteArrayList<Integer> copyOnWriteArrayList1 = new CopyOnWriteArrayList<>();
        copyOnWriteArrayList1.add(1);
        copyOnWriteArrayList1.add(2);
        copyOnWriteArrayList1.add(2,5);
//        copyOnWriteArrayList1.add(4,6);
        System.out.println("index = 0 的值為:" + copyOnWriteArrayList1.get(0));
        System.out.println("index = 1 的值為:" + copyOnWriteArrayList1.get(1));
        System.out.println("index = 2 的值為:" + copyOnWriteArrayList1.get(2));
//        System.out.println("index = 4 的值為:" + copyOnWriteArrayList1.get(4));
        /**
         * 注意:如果使用add(int index, E element),必須保證index的前面的index存在值,不然會報錯。
         *      (可以把上兩行注釋去掉,運行試試結(jié)果)
         */
        /**
         * 4.1、indexOf(E e, int index)
         *           返回第一次出現(xiàn)的指定元素在此列表中的索引,從 index 開始向前搜索,如果沒有找到該元素,則返回 -1。
         * 4.2、indexOf(Object o)
         *           返回此列表中第一次出現(xiàn)的指定元素的索引;如果此列表不包含該元素,則返回 -1。
         */
        CopyOnWriteArrayList<Integer> copyOnWriteArrayList2 = new CopyOnWriteArrayList<>();
        copyOnWriteArrayList2.add(1);
        copyOnWriteArrayList2.add(2);
        copyOnWriteArrayList2.add(3);
        Integer indexFirst = copyOnWriteArrayList2.indexOf(2);
        System.out.println("2的index為:" + indexFirst);
        /**
         * 5.1、lastIndexOf(E e, int index)
         *           返回最后一次出現(xiàn)的指定元素在此列表中的索引,從 index 開始向后搜索,如果沒有找到該元素,則返回 -1。
         * 5.2、lastIndexOf(Object o)
         *           返回此列表中最后出現(xiàn)的指定元素的索引;如果列表不包含此元素,則返回 -1。
         */
        CopyOnWriteArrayList<Integer> copyOnWriteArrayList3 = new CopyOnWriteArrayList<>();
        copyOnWriteArrayList3.add(1);
        copyOnWriteArrayList3.add(2);
        copyOnWriteArrayList3.add(3);
        copyOnWriteArrayList3.add(3);
        copyOnWriteArrayList3.add(4);
        Integer lastIndexOf = copyOnWriteArrayList3.lastIndexOf(3);
        System.out.println("列表中最后出現(xiàn)的指定元素的索引: " + lastIndexOf);
        /**
         * 6、remove(int index) :移除此列表指定位置上的元素,并且此下標(biāo)后面的值會進一位,
         *                      即index為1的值被remove掉,index為2的值就變?yōu)閕ndex為1的值。
         */
        CopyOnWriteArrayList<Integer> copyOnWriteArrayList4 = new CopyOnWriteArrayList<>();
        copyOnWriteArrayList4.add(5);
        copyOnWriteArrayList4.add(6);
        copyOnWriteArrayList4.add(7);
        copyOnWriteArrayList4.add(8);
        Integer removeResult = copyOnWriteArrayList4.remove(1);
        System.out.println("copyOnWriteArrayList4索引為1的值:" + removeResult);
        System.out.println("copyOnWriteArrayList4中是否還存在索引為1的值:" + copyOnWriteArrayList4.get(1));
        /**
         * 7、remove(Object o) :從此列表移除第一次出現(xiàn)的指定元素(如果存在)。
         */
        CopyOnWriteArrayList<String> copyOnWriteArrayList5 = new CopyOnWriteArrayList<>();
        copyOnWriteArrayList5.add("5");
        copyOnWriteArrayList5.add("6");
        copyOnWriteArrayList5.add("6");
        copyOnWriteArrayList5.add("7");
        copyOnWriteArrayList5.add("7");
        System.out.println("沒被remove前的size: " + copyOnWriteArrayList5.size());
        Boolean removeBoolean = copyOnWriteArrayList5.remove("7");
        System.out.println("copyOnWriteArrayList5是否移除7成功?" + removeBoolean);
        System.out.println("index為3的值為:" + copyOnWriteArrayList5.get(3));
        System.out.println("被remove后的size: " + copyOnWriteArrayList5.size());
        /**
         * 8、set(int index, E element) :用指定的元素替代此列表指定位置上的元素。
         */
        CopyOnWriteArrayList<String> copyOnWriteArrayList6 = new CopyOnWriteArrayList<>();
        copyOnWriteArrayList6.add("1");
        copyOnWriteArrayList6.add("2");
        copyOnWriteArrayList6.add("3");
        copyOnWriteArrayList6.add("4");
        copyOnWriteArrayList6.add("5");
        System.out.println("沒使用set()方法前,index = 1 的值為:" + copyOnWriteArrayList6.get(1));
        copyOnWriteArrayList6.set(1,"czd");
        System.out.println("使用set()方法后,index = 1 的值為:" + copyOnWriteArrayList6.get(1));
    }
}

五、總結(jié)

CopyOnWriteArrayList這是一個ArrayList的線程安全的變體,其原理大概可以通俗的理解為:初始化的時候只有一個容器,很長一段時間,這個容器數(shù)據(jù)、數(shù)量等沒有發(fā)生變化的時候,大家(多個線程),都是讀取(假設(shè)這段時間里只發(fā)生讀取的操作)同一個容器中的數(shù)據(jù),所以這樣大家讀到的數(shù)據(jù)都是唯一、一致、安全的,但是后來有人往里面增加了一個數(shù)據(jù),這個時候CopyOnWriteArrayList 底層實現(xiàn)添加的原理是先copy出一個容器(可以簡稱副本),再往新的容器里添加這個新的數(shù)據(jù),最后把新的容器的引用地址賦值給了之前那個舊的的容器地址,但是在添加這個數(shù)據(jù)的期間,其他線程如果要去讀取數(shù)據(jù),仍然是讀取到舊的容器里的數(shù)據(jù)。

到此這篇關(guān)于Java中CopyOnWriteArrayList的使用解析的文章就介紹到這了,更多相關(guān)CopyOnWriteArrayList的使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Maven進行依賴漏洞檢查的實現(xiàn)指南

    使用Maven進行依賴漏洞檢查的實現(xiàn)指南

    在現(xiàn)代軟件開發(fā)中,開源庫的使用變得愈加普遍和重要,然而,這些開源庫中的漏洞往往會成為潛在的安全風(fēng)險,在本文中,我們將探討如何使用 Maven 進行依賴漏洞檢查,以確保項目的安全性和穩(wěn)定性,需要的朋友可以參考下
    2024-05-05
  • 詳解Java中switch的新特性

    詳解Java中switch的新特性

    這篇文章主要介紹了Java中switch的新特性,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Spring實現(xiàn)內(nèi)置監(jiān)聽器

    Spring實現(xiàn)內(nèi)置監(jiān)聽器

    這篇文章主要介紹了Spring 實現(xiàn)自定義監(jiān)聽器案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧,希望能給你帶來幫助
    2021-07-07
  • Java基礎(chǔ)篇之反射機制示例詳解

    Java基礎(chǔ)篇之反射機制示例詳解

    反射是Java可以提供的一個靈活又強大的功能,使用Java反射,您可以知道這個類在運行時具有什么屬性和方法,也可以修改屬性,調(diào)用方法,創(chuàng)建類的實例,這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)篇之反射機制的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Mybatis-Plus實體類繼承Model的使用小結(jié)

    Mybatis-Plus實體類繼承Model的使用小結(jié)

    Mybatis-Plus實體類繼承Model的使用是Mybatis-Plus中的一個重要特性,它允許開發(fā)者通過繼承Model類來快速實現(xiàn)一些通用的功能,本文主要介紹了Mybatis-Plus實體類繼承Model的使用小結(jié),感興趣的可以了解一下
    2024-07-07
  • SpringMVC的簡單傳值(實現(xiàn)代碼)

    SpringMVC的簡單傳值(實現(xiàn)代碼)

    下面小編就為大家?guī)硪黄猄pringMVC的簡單傳值(實現(xiàn)代碼)。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05
  • Java長度不足左位補0的3種實現(xiàn)方法

    Java長度不足左位補0的3種實現(xiàn)方法

    這篇文章主要介紹了Java長度不足左位補0的3種實現(xiàn)方法小結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 淺談Java多線程編程中Boolean常量的同步問題

    淺談Java多線程編程中Boolean常量的同步問題

    這篇文章主要介紹了淺談Java多線程編程中Boolean常量的同步問題,主要針對線程之間同步了不同的布爾對象的問題,需要的朋友可以參考下
    2015-10-10
  • springboot使用spring-data-jpa操作MySQL數(shù)據(jù)庫

    springboot使用spring-data-jpa操作MySQL數(shù)據(jù)庫

    這篇文章主要介紹了springboot使用spring-data-jpa操作MySQL數(shù)據(jù)庫,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • mybatis快速上手并運行程序

    mybatis快速上手并運行程序

    MyBatis 是一款優(yōu)秀的持久層框架,它支持自定義 SQL、存儲過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO為數(shù)據(jù)庫中的記錄
    2022-01-01

最新評論