• CopyOnWriteArrayList


    ArrayList在单线程下是高效的,但是在多线程下是线程不安全的

    ArrayList在多线程的线程不安全的几种体现

    1. 删除元素时。a和b同时删除索引为4个数据。这个时候a线程先执行 将4后面的元素往前移动一位。size--  这个时候b线程也删除 就删除到别的元素。如果是删除第一个元素。a线程size--后。a再功能size去获取 就会报索引越界
    2. 添加元素时 a b线程同时add   a 判断这时往下标为0的位置加元素 size还没++   这个时候b也执行add方法也是判断往下标为0的地方添加元素  a往下标为0的位置填入数据 size++  b也往0的位置添加元素 覆盖了a的值 size++  这个时候遍历会出现索引溢出
    3. 同时读和删的时候同理。for i++ 这个时候元素已经删除了。。或者移动了 导致数据错乱(因为list本质是数组 删除元素 只将后面元素往前移)
    4. 迭代器如何解决又在读又在写的问题 可以参考https://www.cnblogs.com/LQBlog/p/12713238.html#autoid-6-2-0
     public static void main(String[] args) throws InterruptedException {
            // CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<String>();
          //  Vector<String> list=new Vector<String>();
            List<String> list = new ArrayList<String>();
            new Thread(new Runnable() {
                @Override
                public void run() {
                        while (true) {
    
                            for (int i = 0; i < list.size(); i++) {
                                list.get(i);
                            }
                        }
                }
            }).start();
            for (int i = 0; i < 2; i++) {
                new Thread(new Runnable() {
                    int j = 0;
                    @Override
                    public void run() {
                        while (j < 1000) {
                            j++;
                            list.add("test");
                        }
    
                    }
                }).start();
            }
            Thread.sleep(5000);
            System.out.println(list.size());
        }

    执行这段代码会报索引溢出。。使用注释的代码便不会。Vector 跟hashTable一样 在所有方法都加了sychronized关键字。性能很低

    CopyOnWriteArrayList 只是在add的时候加了锁 读的时候没加锁。   在写的时候将原来数组copy一份。然后加入新的值 再将新的数组引用替换旧的数组引用达到了读写分离。

    CopyOnWriteArrayList 使用需要注意的几个点

    在读多写少的时候使用

    因为CopyOnWriteArrayList为了保证添加的时候副本只有一个 在add方法是加了锁的

    在不要求数据实时性的时候使用

    CopyOnWriterArrayList为了提高多线程访问的效率。在读时没有加锁。但是在写的时候操作的是副本 读的时候操作的是原来的容器

  • 相关阅读:
    android使用广播退出应用程序
    Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW _TASK flag.
    Android获取屏幕尺寸大小
    onActivityResult不被执行的问题。
    ADB操作多台设备
    在Eclipse的DDMS中查看手机data文件夹中的内容
    JDK版本过高,导致Eclipse报错
    Android colors.xml
    Eclipse智能提示
    在配置IIS负载均衡时,引起的一系列问题
  • 原文地址:https://www.cnblogs.com/LQBlog/p/8733335.html
Copyright © 2020-2023  润新知