`
zy116494718
  • 浏览: 473211 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ArrayList 和 CopyOnWriteArrayList 线程安全测试

    博客分类:
  • Java
 
阅读更多

ArrayList 是 非线程安全的, CopyOnWriteArrayList 是一个线程安全,并且在读操作时无锁的ArrayList,且适合并发访问。对于集合元素数为10000,线程数量为100的情况下进行性能测试,随着元素数量和线程数量的增加,CopyOnWriteArrayList在增加元素和删除元素时的性能下降非常明显,并且性能会比ArrayList低。但在查找元素这点上随着线程数的增长,性能较ArrayList会好很多。

 

故在读多写少的并发场景中,CopyOnWriteArrayList较之ArrayList是更好的选择。

 

 

下面对两种方式的线程安全进行下测试:

 

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class ThreadSafeDemo {
    public static int demo(final List list, final int testCount) throws InterruptedException {
        ThreadGroup group = new ThreadGroup(list.getClass().getName() + "@" + list.hashCode()); 
        final Random rand = new Random(); 
        
        Runnable listAppender = new Runnable() {  // 这里面实现了Runnable接口类,覆盖了它的run方法
            public void run() {
                try {
                    Thread.sleep(rand.nextInt(2));
                } catch (InterruptedException e) {
                    return; 
                } 
                list.add("0"); 
            }
        }; 
        
        for (int i = 0; i < testCount; i++) {
            new Thread(group, listAppender, "InsertList-" + i).start(); 
                             //java.lang.Thread
.Thread(ThreadGroup
 group, Runnable
 target, String
 name)
        
      }
        
        while (group.activeCount() > 0) {
            Thread.sleep(10); 
        }
        
        return list.size(); 
    }
    public static void main(String[] args) throws InterruptedException {
        List unsafeList = new ArrayList(); 
        List safeList = Collections.synchronizedList(new ArrayList()); // 也可以换成new CopyToWriteArrayList
        final int N = 10000; 
        for (int i = 0; i < 10; i++) {
            unsafeList.clear(); 
            safeList.clear(); 
            int unsafeSize = demo(unsafeList, N); 
            int safeSize = demo(safeList, N); 
            System.out.println("unsafe/safe: " + unsafeSize + "/" + safeSize); 
        }
    }
}

 

测试的结果为:

unsafe/safe: 9992/10000
unsafe/safe: 9996/10000
unsafe/safe: 9990/10000
unsafe/safe: 9992/10000
unsafe/safe: 9997/10000
unsafe/safe: 9997/10000
unsafe/safe: 9993/10000
unsafe/safe: 9995/10000
unsafe/safe: 9993/10000
unsafe/safe: 9995/10000

 

之所以会造成不安全线程list数不足10000,主要有两点:

首先我们来看ArrayList的源码:

 

public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}

 

主要问题出在size++这块,因为该方法不是线程安全的,所以就有可能出现以下两种情况:

1)线程A和线程B同样取得size=10,然后在相同位置10插入了两遍值,然后在都执行size++,结果size变成了12,这样下次再有线程进来时会在12的位置继续插入值,而11则变成了null,实验下果然如此,但是其实这并不能解释为什么list1.size的值会减少,只能解释为什么list中有的值为null

2) size++这个操作同样不是线程安全的,它分成两个步骤,第一,取size的位置,第二,size位置+1,这样就有可能A线程和B线程同时取到size的位置,然后+1,这样A,B线程执行完size++后,size的值为11而不是12,所以就会有不同的线程同时在一个位置赋值,导致list的数量不足。

 

 

 

 

分享到:
评论

相关推荐

    集合ArrayList测试集合ArrayList测试集合ArrayList测试

    在实际应用中,选择`ArrayList`还是其他集合类型,如`LinkedList`或`HashSet`,应根据具体需求来决定,例如是否需要保持元素顺序、是否频繁进行插入和删除、是否需要线程安全等。 总结来说,`ArrayList`是Java集合...

    ArrayList源码和多线程安全问题分析

    ArrayList源码和多线程安全问题分析 在 Java 编程语言中,ArrayList 是一个常用的集合类,它提供了动态数组的实现,能够存储大量的数据。但是,在多线程环境下,ArrayList 并不是线程安全的。这篇文章主要介绍了 ...

    Java多线程安全集合

    这些集合确保了在多个线程访问时的数据一致性、完整性和安全性,避免了竞态条件、死锁和其他并发问题。Java提供了一系列的线程安全集合类,它们是专门为多线程环境设计的。 首先,我们要了解什么是线程安全。线程...

    Java中ArrayList和Vector的区别共2页.p

    如果需要线程安全的动态数组,可以选择Vector,但应考虑其性能影响,也可以考虑使用`Collections.synchronizedList(List&lt;T&gt; list)`将ArrayList转换为线程安全的列表,或者使用`CopyOnWriteArrayList`,它在读多写少...

    ArrayList和Linkedlist1

    此外,对于大数据量的情况,考虑使用并发集合,如ConcurrentLinkedQueue或CopyOnWriteArrayList,以提高多线程环境下的性能。 总的来说,理解ArrayList和LinkedList的基本特性和应用场景,以及如何处理与之相关的...

    Java集合教程吐血整理干货.md

    HashMap是线程不安全的,并允许null key 和 null value。 HashMap在我当前的jdk版本(11)的默认容量为0,在第一次添加元素的时候才初始化容量为 16, 之后才扩容为原来的2倍。 HashMap的扩容是根据 threshold决定的 : ...

    ArrayList LinkedList Vector性能对比

    2. **线程安全**:ArrayList和LinkedList不是线程安全的,如果在多线程环境中使用,需要手动添加同步机制,或者选择Vector。 3. **内存消耗**:LinkedList比ArrayList和Vector占用更多的内存,因为它需要存储额外的...

    java并发容器CopyOnWriteArrayList实现原理及源码分析

    Java并发容器CopyOnWriteArrayList是Java并发包中提供的一个并发容器,实现了线程安全且读操作无锁的ArrayList,写操作则通过创建底层数组的新副本来实现。这种读写分离的并发策略使得CopyOnWriteArrayList容器允许...

    java集合-CopyOnWriteArrayList的使用

    在Java中,CopyOnWriteArrayList(写入时复制数组列表)是线程安全的集合类,它实现了List接口,并使用了"写入时复制"的策略来保证线程安全性。 CopyOnWriteArrayList的主要特点是:在进行修改操作(例如添加、修改...

    第8讲 对比Vector、ArrayList、LinkedList有何区别1

    同时,关注集合框架的并发支持,如ConcurrentHashMap和CopyOnWriteArrayList等,它们在多线程环境下的性能优化至关重要。 最后,了解集合框架的发展历程,比如从Java 1.0到现在的改进,可以帮助你更好地理解设计...

    ArrayList演示

    如果需要线程安全,可以考虑使用`Collections.synchronizedList()`将ArrayList转换为线程安全的列表,或者使用`CopyOnWriteArrayList`类。 ArrayList的容量会随着元素数量的增加自动扩展。默认情况下,当容量达到...

    ArrayList,HashMap

    对于并发场景,可以使用CopyOnWriteArrayList(线程安全的ArrayList变体)和ConcurrentHashMap(线程安全的HashMap变体)。 总之,ArrayList和HashMap是Java集合框架中的重要组件,理解它们的工作原理和适用场景,...

    简单测试代码

    如果需要线程安全,可以考虑使用CopyOnWriteArrayList。 2. **随机访问**:由于ArrayList基于数组,所以可以通过索引来快速访问任何位置的元素,随机访问性能优秀。 3. **增删操作效率**:在ArrayList的末尾添加或...

    Java中ArrayList类的用法知识.pdf

    在多线程环境下,要么使用`synchronized`方法,要么使用`CopyOnWriteArrayList`(线程安全但不支持修改操作)。 - 使用线程安全的ArrayList可能会降低性能,因为每次操作都需要进行同步。 总的来说,ArrayList是...

    ArrayList集合工具类

    通过查看源代码,我们可以学习到如何在JavaScript环境中模拟ArrayList的行为,以及如何处理与Java中的ArrayList不同的问题,如线程安全和动态扩容等。 总的来说,ArrayList集合工具类是Java编程中的核心组件,它在...

    深入Java集合学习系列:ArrayList的实现原理

    如果需要在并发环境中使用,可以选择使用Collections.synchronizedList()方法将ArrayList转换为线程安全的列表,或者使用并发集合如CopyOnWriteArrayList。 ArrayList的效率特点在于随机访问速度快,因为可以通过...

    ArrayList的学习821.docx

    因此,如果在多线程场景下,写操作频繁,考虑使用线程安全的集合类,如`CopyOnWriteArrayList`,它在写操作时复制一份新的数组,避免了同步带来的性能损失。 总的来说,ArrayList是Java中常用的一种数据结构,适用...

    ArrayList源码分析

    如果需要线程安全的列表,应使用`CopyOnWriteArrayList`。 7. **ArrayList与LinkedList的比较** - ArrayList更适合于随机访问,插入和删除在中间位置较慢。 - LinkedList适合于频繁的插入和删除,但随机访问性能...

    JDK1.6中Arraylist,Vector,LinkedList源码

    在JDK 1.6中,ArrayList提供了线程不安全的高效操作,适合于非并发环境下的高性能读写操作。其优点在于随机访问快速,因为数组支持索引直接访问;缺点是插入和删除元素需要移动后续元素,效率较低。 Vector与...

    Java线程安全的常用类_动力节点Java学院整理

    此外,在Java中,还有很多非线程安全的类和接口,例如ArrayList、LinkedList、HashMap等。这些类的方法都不是同步的,每次可以有多个访问。如果在多线程环境中使用这些类,需要手动添加同步机制,以避免线程安全问题...

Global site tag (gtag.js) - Google Analytics