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

Java中CopyOnWriteArrayList的使用解析

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

一、CopyOnWriteArrayList介紹

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

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

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

二、CopyOnWriteArrayList 有幾個(gè)缺點(diǎn)

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

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

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

三、CopyOnWriteArrayList的一些方法

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

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

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

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

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

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)順序在此列表元素上進(jìn)行迭代的迭代器,返回值為 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() :返回此列表中的元素?cái)?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)建一個(gè)空列表。
         * CopyOnWriteArrayList(Collection<? extends E> c):
         *           創(chuàng)建一個(gè)按 collection 的迭代器返回元素的順序包含指定 collection 元素的列表。
         * CopyOnWriteArrayList(E[] toCopyIn):
         *           創(chuàng)建一個(gè)保存給定數(shù)組的副本的列表。
         */
        /**
         * 1、add(E e) :將指定元素添加到此列表的尾部,返回值為boolean。
         *
         * 2、iterator() :返回以恰當(dāng)順序在此列表元素上進(jìn)行迭代的迭代器,返回值為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存在值,不然會(huì)報(bào)錯(cuò)。
         *      (可以把上兩行注釋去掉,運(yùn)行試試結(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)后面的值會(huì)進(jìn)一位,
         *                      即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這是一個(gè)ArrayList的線程安全的變體,其原理大概可以通俗的理解為:初始化的時(shí)候只有一個(gè)容器,很長(zhǎng)一段時(shí)間,這個(gè)容器數(shù)據(jù)、數(shù)量等沒有發(fā)生變化的時(shí)候,大家(多個(gè)線程),都是讀取(假設(shè)這段時(shí)間里只發(fā)生讀取的操作)同一個(gè)容器中的數(shù)據(jù),所以這樣大家讀到的數(shù)據(jù)都是唯一、一致、安全的,但是后來有人往里面增加了一個(gè)數(shù)據(jù),這個(gè)時(shí)候CopyOnWriteArrayList 底層實(shí)現(xiàn)添加的原理是先copy出一個(gè)容器(可以簡(jiǎn)稱副本),再往新的容器里添加這個(gè)新的數(shù)據(jù),最后把新的容器的引用地址賦值給了之前那個(gè)舊的的容器地址,但是在添加這個(gè)數(shù)據(jù)的期間,其他線程如果要去讀取數(shù)據(jù),仍然是讀取到舊的容器里的數(shù)據(jù)。

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

相關(guān)文章

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

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

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

    詳解Java中switch的新特性

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

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

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

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

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

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

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

    SpringMVC的簡(jiǎn)單傳值(實(shí)現(xiàn)代碼)

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

    Java長(zhǎng)度不足左位補(bǔ)0的3種實(shí)現(xiàn)方法

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

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

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

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

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

    mybatis快速上手并運(yùn)行程序

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

最新評(píng)論