zoukankan      html  css  js  c++  java
  • CopyOnWriteArrayList 学习笔记

    先简单说一下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

  • 相关阅读:
    arm,iptables: No chain/target/match by that name.
    Windows7-USB-DVD-tool提示不能拷贝文件的处理
    WPF实现WORD 2013墨迹批注功能
    windows下实现屏幕分享(C#)
    Owin WebAPI上传文件
    js 下不同浏览器,new Date转换结果时差
    jquery 动态增加的html元素,初始化设置在id或class上的事件无效
    WPF DataGrid模拟click实现效果
    基于Bootstrap的步骤引导html页面
    XWalkView+html 开发Android应用
  • 原文地址:https://www.cnblogs.com/yinkh/p/6340509.html
Copyright © 2011-2022 走看看