简单说一下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<? extends E> c) {elementData = c.toArray();elementCount = elementData.length;// c.toArray might (incorrectly) not return Object[] (see 6260652)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 workfor (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<E> list) {super(list);this.list = list;}SynchronizedList(List<E> 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<? extends E> c) {synchronized (mutex) {return list.addAll(index, c);}}public ListIterator<E> listIterator() {return list.listIterator(); // Must be manually synched by user}public ListIterator<E> listIterator(int index) {return list.listIterator(index); // Must be manually synched by user}public List<E> subList(int fromIndex, int toIndex) {synchronized (mutex) {return new SynchronizedList<>(list.subList(fromIndex, toIndex),mutex);}}@Overridepublic void replaceAll(UnaryOperator<E> operator) {synchronized (mutex) {list.replaceAll(operator);}}@Overridepublic void sort(Comparator<? super E> 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);}

Java中线程安全的List相关推荐

  1. JAVA中线程同步的方法(7种)汇总

    JAVA中线程同步的方法(7种)汇总 同步的方法: 一.同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法. ...

  2. java中线程的生命周期

    文章目录 java中Thread的状态 NEW Runnable BLOCKED WAITING TIMED_WAITING TERMINATED java中线程的生命周期 线程是java中绕不过去的 ...

  3. java中线程的6种状态

    java中线程的状态分为6种. 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法. 2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running ...

  4. Java中线程池,你真的会用吗

    转载自   Java中线程池,你真的会用吗 在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Ex ...

  5. java中线程死锁及避免_如何避免Java线程中的死锁?

    java中线程死锁及避免 如何避免Java中的死锁? 是Java面试中最受欢迎的问题之一,也是本季多线程的风格,主要是在高层提出,并带有很多后续问题. 尽管问题看起来很基础,但是一旦您开始深入研究,大 ...

  6. 关于java中线程yield()方法问题

    关于java中线程yield()方法问题 问题一: 我知道yield是用来休眠当前线程,但我查看了资料,又说其不会释放锁,所以我就不解了,其明明会将cpu资源给其他线程,那它不释放锁,其他线程有怎么获 ...

  7. Java中线程池,你真的会用吗?

    在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Executors静态工厂构建线程池,但一般不建 ...

  8. 面试官:Java中线程是按什么顺序执行的?

    本文分享自华为云社区<[高并发系列]Java中线程到底是按什么顺序执行的?你了解的可能是错误的!>,原文作者:冰 河 . Java中线程的执行顺序可能与你想的不一样!一文解密多线程的执行顺 ...

  9. java中线程的状态以及线程栈分析

    java中线程的状态 状态 说明 NEW 初始状态.线程刚刚被创建,并且start()方法还未被调用 RUNNABLE 运行状态.表示线程正在java虚拟机中执行,但是可能正在等待操作系统的其他资源, ...

  10. Java中线程的创建有两种方式

    Java中继承thread类与实现Runnable接口的区别 Java中线程的创建有两种方式: 1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2.  通过 ...

最新文章

  1. 5 修改request对象变量_【总结】前端5大常见设计模式,代码一看你就懂!
  2. 死锁产生条件-不剥夺条件
  3. Mac MacBook Pro的移动硬盘方案
  4. kafka 削峰_从面试角度一文学完 Kafka
  5. .NET Core开发实战(第18课:日志框架:聊聊记日志的最佳姿势)--学习笔记(上)...
  6. 计算机控制用户自己编写什么软件吗,计算机控制软件技术基础.ppt
  7. atoi(s)函数用法
  8. lnmp mysql 自动关闭_mysql总是自动停止 日志提示Plugin ‘FEDERATED’ is disabled的解决办法...
  9. 个位数统计(java)
  10. 2018 年大疆机器学习算法工程师春季提前批笔试题
  11. 【从C到C++学习笔记】bool类型/const限定符/#define//结构体对齐
  12. WireGuard 教程:使用 DNS-SD 进行 NAT-to-NAT 穿透
  13. 西数发布首款消费级SSD:蓝盘、绿盘齐飞
  14. phpstorm运行php项目步骤
  15. PaddleOCR实现高精度车牌识别
  16. C语言实现url的编码和解码
  17. Android黄油计划之Choreographer原理解析
  18. 写一个在线位图字体制作工具!BitmapFont!
  19. 六、Spring Boot整合Shiro
  20. sheng的学习笔记-设计模式-代理模式

热门文章

  1. FPGA:设计一个原码一位乘法器
  2. Linux之常见的通配符
  3. win7 virtualbox VBoxDD.DLL 0x80004005 uxtheme.dll 错误
  4. thickBox参数详解
  5. Ubuntu下安装mplayer
  6. VB中随机数ab的比较大小
  7. 【清风数模】 相关系数(理论知识+代码实操 保姆级笔记)
  8. matlab的实验报告,MATLAB实验报告(8个实验).doc
  9. bzoj-2150 部落战争
  10. 子域名收集工具——Sublist3r