Java中线程安全的List

Java中线程安全的List简单说一下 java 中线程安全的 List 一 VectorVector 是大家熟知的线程安全的 List 集合 不过他的性能是最差 所有的方法都是加了 synchronized 来同步 从而保证线程安全 源码也是使用数组来存储数据 有以下构造方法 Constructsan

简单说一下java中线程安全的List 

一、Vector

Vector是大家熟知的线程安全的List集合,不过他的性能是最差,所有的方法都是加了synchronized来同步,从而保证线程安全。

源码也是使用数组来存储数据,有以下构造方法。 

 / * Constructs an empty vector with the specified initial capacity and * capacity increment. * * @param initialCapacity the initial capacity of the vector * @param capacityIncrement the amount by which the capacity is * increased when the vector overflows * @throws IllegalArgumentException if the specified initial capacity * is negative */ public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; this.capacityIncrement = capacityIncrement; } / * Constructs an empty vector with the specified initial capacity and * with its capacity increment equal to zero. * * @param initialCapacity the initial capacity of the vector * @throws IllegalArgumentException if the specified initial capacity * is negative */ public Vector(int initialCapacity) { this(initialCapacity, 0); } / * Constructs an empty vector so that its internal data array * has size {@code 10} and its standard capacity increment is * zero. */ public Vector() { this(10); } / * Constructs a vector containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this * vector * @throws NullPointerException if the specified collection is null * @since 1.2 */ public Vector(Collection 
   c) { elementData = c.toArray(); elementCount = elementData.length; // c.toArray might (incorrectly) not return Object[] (see ) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, elementCount, Object[].class); }

它的增加、修改、获取、删除等都通过synchronized来同步。

 public synchronized void insertElementAt(E obj, int index) { modCount++; if (index > elementCount) { throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); } ensureCapacityHelper(elementCount + 1); System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); elementData[index] = obj; elementCount++; } public synchronized void addElement(E obj) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = obj; } public synchronized boolean removeElement(Object obj) { modCount++; int i = indexOf(obj); if (i >= 0) { removeElementAt(i); return true; } return false; } public synchronized void removeAllElements() { modCount++; // Let gc do its work for (int i = 0; i < elementCount; i++) elementData[i] = null; elementCount = 0; } public synchronized E get(int index) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); return elementData(index); } public synchronized E set(int index, E element) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }

二、Collections.SynchronizedList

SynchronizedList是Collections类的静态内部类,它能把所有 List 接口的实现类转换成线程安全的List,比 Vector 有更好的扩展性和兼容性。

SynchronizedList的构造方法如下:

 SynchronizedList(List 
  
    list) { super(list); this.list = list; } SynchronizedList(List 
   
     list, Object mutex) { super(list, mutex); this.list = list; } 
    
  

SynchronizedList的部分方法源码如下:

public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) {return list.equals(o);} } public int hashCode() { synchronized (mutex) {return list.hashCode();} } public E get(int index) { synchronized (mutex) {return list.get(index);} } public E set(int index, E element) { synchronized (mutex) {return list.set(index, element);} } public void add(int index, E element) { synchronized (mutex) {list.add(index, element);} } public E remove(int index) { synchronized (mutex) {return list.remove(index);} } public int indexOf(Object o) { synchronized (mutex) {return list.indexOf(o);} } public int lastIndexOf(Object o) { synchronized (mutex) {return list.lastIndexOf(o);} } public boolean addAll(int index, Collection 
   c) { synchronized (mutex) {return list.addAll(index, c);} } public ListIterator 
  
    listIterator() { return list.listIterator(); // Must be manually synched by user } public ListIterator 
   
     listIterator(int index) { return list.listIterator(index); // Must be manually synched by user } public List 
    
      subList(int fromIndex, int toIndex) { synchronized (mutex) { return new SynchronizedList<>(list.subList(fromIndex, toIndex), mutex); } } @Override public void replaceAll(UnaryOperator 
     
       operator) { synchronized (mutex) {list.replaceAll(operator);} } @Override public void sort(Comparator 
       c) { synchronized (mutex) {list.sort(c);} } / * SynchronizedRandomAccessList instances are serialized as * SynchronizedList instances to allow them to be deserialized * in pre-1.4 JREs (which do not have SynchronizedRandomAccessList). * This method inverts the transformation. As a beneficial * side-effect, it also grafts the RandomAccess marker onto * SynchronizedList instances that were serialized in pre-1.4 JREs. * * Note: Unfortunately, SynchronizedRandomAccessList instances * serialized in 1.4.1 and deserialized in 1.4 will become * SynchronizedList instances, as this method was missing in 1.4. */ private Object readResolve() { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : this); } 
      
     
    
  

它所有方法都是带同步对象锁的,和 Vector 一样,它不是性能最优的。

三、CopyOnWriteArrayList

CopyOnWriteArrayList是java1.5以后才加入的新类,从命名可以理解为复制在写入的List。

它的添加时加锁的(ReentrantLock ,非synchronized同步锁),读操作是没有加锁。

添加和删除方法部分代码实现:

 public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } } private boolean remove(Object o, Object[] snapshot, int index) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] current = getArray(); int len = current.length; if (snapshot != current) findIndex: { int prefix = Math.min(index, len); for (int i = 0; i < prefix; i++) { if (current[i] != snapshot[i] && eq(o, current[i])) { index = i; break findIndex; } } if (index >= len) return false; if (current[index] == o) break findIndex; index = indexOf(o, current, index, len); if (index < 0) return false; } Object[] newElements = new Object[len - 1]; System.arraycopy(current, 0, newElements, 0, index); System.arraycopy(current, index + 1, newElements, index, len - index - 1); setArray(newElements); return true; } finally { lock.unlock(); } }

添加或者删除元素时,先加锁,再进行复制替换操作,最后再释放锁。 

它的优势在于,读操作是不加任和锁。这样做的好处是,在高并发情况下,读取元素时就不用加锁,写数据时才加锁,大大提升了读取性能。

看下它的 get 方法源码:

 private E get(Object[] a, int index) { return (E) a[index]; } / * {@inheritDoc} * * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { return get(getArray(), index); }

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/224958.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 上午10:45
下一篇 2026年3月17日 上午10:45


相关推荐

  • vue 父组件调用子组件的方法_vue子组件修改父组件值

    vue 父组件调用子组件的方法_vue子组件修改父组件值我们都知道通过$ref可以获取到某个DOM,但是它也可以用来获取子组件的实例,调用子组件的方法例:子组件:&amp;lt;template&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/template&amp;gt;&amp;lt;script&amp;gt;exportdefault{methods:{c

    2022年10月2日
    5
  • Js如何防止页面后退(使浏览器后退按钮失效)[通俗易懂]

    Js如何防止页面后退(使浏览器后退按钮失效)[通俗易懂]以下代码仅供参考:&lt;scripttype="text/javascript"&gt; $(function(){//防止页面后退history.pushState(null,null,"localhost:8080");window.addEventListener(‘popstate’,function(){…

    2022年7月25日
    15
  • mybatis-plus IPage分页踩坑

    mybatis-plus IPage分页踩坑mybatis plusIPage 分页多参数查询莫名的异常 1 Mapper2 Mapper xml3 TooManyResul 问题解决 mybatis plus 中 page 参数不在第一个位置 返回的结果集接收对象不被认为是一个集合 而放在第一位就没有问题 所以正确的写法是莫名的异常 1 MapperIPage Entity findByDataSt Entity

    2026年3月16日
    2
  • Ubuntu下的解压缩

    一.命令:.tar 解包:tarxvfFileName.tar打包:tarcvfFileName.tarDirName(注:tar是打包,不是压缩!)—————————————

    2021年12月28日
    42
  • 普罗米修斯监控系统搭建(MAC环境基于Docker)「建议收藏」

    普罗米修斯监控系统搭建(MAC环境基于Docker)「建议收藏」采用Docker环境搭建方式可以快速搭建起测试学习环境第一步:下载docker镜像dockerpullprom/node-exporterdockerpullprom/prometheusdockerpullgrafana/grafana第二步:启动exporter(理解为内置好的监控埋点)dockerrun-d-p9100:9100\-v”/proc:/host/proc:ro”\-v”/sys:/host/sys:ro”\-v”/:/roo

    2022年7月19日
    53
  • StopWatch类

    StopWatch类背景有时我们在做开发的时候需要记录每个任务执行时间,或者记录一段代码执行时间,最简单的方法就是打印当前时间与执行完时间的差值,然后这样如果执行大量测试的话就很麻烦,并且不直观,如果想对执行的时间做进一步控制,则需要在程序中很多地方修改,目前spring-framework提供了一个StopWatch类可以做类似任务执行时间控制,也就是封装了一个对开始时间,结束时间记录操作的Java类,小例一则如…

    2022年6月23日
    30

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号