CopyOnWriteArrayList 学习笔记

本文通过两个示例对比展示了CopyOnWriteArrayList与普通ArrayList在并发修改时的不同表现,揭示了CopyOnWrite机制如何解决迭代器失效的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先简单说一下CopyOnWrite是什么意思?

Copy-On-Write简称COW,是一种用于程序设计中的优化策略。其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。从JDK1.5开始Java并发包里提供了

两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器非常有用,可以在非常多的并发场景中使用到。

 

下面自己写了两个例子基本可以说明其作用

例一:不使用CopyOnWriteArrayList

package com.dushu817.exprise.javaexprise.concurrent.copyonwrite;

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

public class NoUseCopyOnWriteTest {

    static List<String> task = new ArrayList<>();
    
    static void initTask() {
        task.add("1");
        task.add("2");
        task.add("3");
    }
    
    public static void main(String[] args) {
        // 初始化任务队列
        initTask();
        // 获取任务队列迭代器
        Iterator<String> iter = task.iterator();
        // 启动子线程
        new Thread(()->{
            task.add("4");
        }).start();
        
        // 主线程等待
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 遍历任务队列
        while (iter.hasNext()) {
            System.out.println(iter.next());
        }
        
        // 重新遍历
        iter = task.iterator();
        while (iter.hasNext()) {
            System.out.println(iter.next());
        }
    }
    
}

执行会抛异常   

 

例二:使用CopyOnWriteArrayList

package com.dushu817.exprise.javaexprise.concurrent.copyonwrite;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

public class CopyOnWriteTest {

    static List<String> task = new CopyOnWriteArrayList<>();
    
    static void initTask() {
        task.add("1");
        task.add("2");
        task.add("3");
    }
    
    public static void main(String[] args) {
        // 初始化任务队列
        initTask();
        // 获取任务队列迭代器
        Iterator<String> iter = task.iterator();
        // 启动子线程
        new Thread(()->{
            task.add("4");
        }).start();
        
        // 主线程等待
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 遍历任务队列
        while (iter.hasNext()) {
            System.out.println(iter.next());
        }
        
        // 重新遍历
        iter = task.iterator();
        while (iter.hasNext()) {
            System.out.println(iter.next());
        }
    }
    
}

执行结果:

 

可以看到,第一次遍历时,虽然集合中的元素已经修改,但是迭代器中的元素仍为初始值。第二次遍历才变成修改后的值。

 

这两个例子同时也说明了CopyOnWrite的一个缺点,数据不能保证实时一致,但是最终会一致。如果希望写入的数据可以马上读到,请不要使用CopyOnWrite

posted on 2017-01-22 15:41 yin.kh 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/yinkh/p/6340509.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值