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++  这个时候遍历会出现索引溢出
 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为了提高多线程访问的效率。在读时没有加锁。但是在写的时候操作的是副本 读的时候操作的是原来的容器

 

转载于:https://www.cnblogs.com/LQBlog/p/8733335.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CopyOnWriteArrayList是一个线程安全的List实现,它通过每次修改操作(添加、删除、修改)时都创建一个新的底层数组来实现线程安全性。 CopyOnWriteArrayList的特点如下: 1. 线程安全:多个线程可以同时读取CopyOnWriteArrayList的内容,而不需要额外的同步机制。这使得它非常适合在读操作远远多于写操作的场景使用。 2. 写操作的代价较高:每次对CopyOnWriteArrayList进行写操作时,都会创建一个新的底层数组,因此写操作的代价较高。 3. 实时性较低:由于写操作会创建新的底层数组,读取操作可能会看到旧的数据,因此CopyOnWriteArrayList的实时性较低。 使用CopyOnWriteArrayList的示例代码如下: ```java import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("Hello"); list.add("World"); for (String item : list) { System.out.println(item); } } } ``` 在上述代码,我们创建了一个CopyOnWriteArrayList,并向其添加了两个元素。然后使用增强for循环遍历CopyOnWriteArrayList的元素,并打印输出。 需要注意的是,CopyOnWriteArrayList适用于读操作远远多于写操作的场景,如果写操作非常频繁,可能会导致性能问题。此外,CopyOnWriteArrayList不保证元素的顺序性,因为在写操作时会创建新的底层数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值