`
zy116494718
  • 浏览: 476769 次
  • 性别: 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的数量不足。

 

 

 

 

分享到:
评论

相关推荐

    Java集合多线程安全.docx

    在Java编程中,集合框架是数据管理的核心部分。...此外,Java并发库(如`ConcurrentHashMap`、`CopyOnWriteArrayList`等)提供了更高效且线程安全的解决方案,可以在性能和线程安全之间找到更好的平衡。

    (Java源码阅读) ArrayList为什么线程不安全?

    然而,ArrayList并不是线程安全的,这意味着在多线程环境下,如果多个线程同时对ArrayList进行操作,特别是结构上的修改,可能会导致数据不一致或者抛出异常。线程不安全主要体现在以下几个方面: 1. **无同步处理...

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

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

    Java多线程安全集合

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

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

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

    Java常见的线程安全的类.docx

    线程安全的集合对象,如Vector、HashTable和StringBuffer,相比于非线程安全的ArrayList、LinkedList、HashMap、HashSet、TreeMap和TreeSet、StringBuilder等,提供了额外的线程安全保障,但可能会牺牲一定的性能。...

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

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

    线程安全Vector

    虽然 `Vector` 在某些情况下可以满足需求,但由于其性能问题和潜在的线程安全陷阱,现代Java编程实践中更倾向于使用其他集合类,如 `ArrayList` 或并发集合类。理解不同集合类的特点及其适用场景对于编写高效、可靠...

    ArrayList和Linkedlist1

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

    并发编程实践,全面介绍基础知识、JVM同步原语、线程安全、低级并发工具、线程安全容器、高级线程协作工具、Executor部分等

    - **并发容器**:如ArrayList、HashMap的并发版本(CopyOnWriteArrayList、ConcurrentHashMap),设计为线程安全,但效率更高。 - **阻塞队列**:如ArrayBlockingQueue、LinkedBlockingQueue,提供生产者-消费者...

    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的容量会随着元素数量的增加自动扩展。默认情况下,当容量达到...

    对比Vector、ArrayList、LinkedList1

    - **效率**:由于没有线程安全的开销,ArrayList在单线程环境中的效率更高,特别适合于频繁进行随机访问和尾部插入、删除操作的场景。 3. **LinkedList** - **数据结构**:LinkedList是基于双向链表实现的,每个...

    ArrayList,HashMap

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

    简单测试代码

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

    ArrayList源码分析.docx 等

    在设计和使用 ArrayList 时,需要考虑线程安全问题,并根据实际需求选择合适的构造方法和操作方式。在面试中,深入理解 ArrayList 的源码和其与其他数据结构的区别是展示 Java 基础技能的重要方面。

    Java中ArrayList类的用法知识.pdf

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

Global site tag (gtag.js) - Google Analytics