Java中线程安全的List
简单说一下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相关推荐
- JAVA中线程同步的方法(7种)汇总
JAVA中线程同步的方法(7种)汇总 同步的方法: 一.同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法. ...
- java中线程的生命周期
文章目录 java中Thread的状态 NEW Runnable BLOCKED WAITING TIMED_WAITING TERMINATED java中线程的生命周期 线程是java中绕不过去的 ...
- java中线程的6种状态
java中线程的状态分为6种. 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法. 2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running ...
- Java中线程池,你真的会用吗
转载自 Java中线程池,你真的会用吗 在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Ex ...
- java中线程死锁及避免_如何避免Java线程中的死锁?
java中线程死锁及避免 如何避免Java中的死锁? 是Java面试中最受欢迎的问题之一,也是本季多线程的风格,主要是在高层提出,并带有很多后续问题. 尽管问题看起来很基础,但是一旦您开始深入研究,大 ...
- 关于java中线程yield()方法问题
关于java中线程yield()方法问题 问题一: 我知道yield是用来休眠当前线程,但我查看了资料,又说其不会释放锁,所以我就不解了,其明明会将cpu资源给其他线程,那它不释放锁,其他线程有怎么获 ...
- Java中线程池,你真的会用吗?
在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Executors静态工厂构建线程池,但一般不建 ...
- 面试官:Java中线程是按什么顺序执行的?
本文分享自华为云社区<[高并发系列]Java中线程到底是按什么顺序执行的?你了解的可能是错误的!>,原文作者:冰 河 . Java中线程的执行顺序可能与你想的不一样!一文解密多线程的执行顺 ...
- java中线程的状态以及线程栈分析
java中线程的状态 状态 说明 NEW 初始状态.线程刚刚被创建,并且start()方法还未被调用 RUNNABLE 运行状态.表示线程正在java虚拟机中执行,但是可能正在等待操作系统的其他资源, ...
- Java中线程的创建有两种方式
Java中继承thread类与实现Runnable接口的区别 Java中线程的创建有两种方式: 1. 通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2. 通过 ...
最新文章
- 5 修改request对象变量_【总结】前端5大常见设计模式,代码一看你就懂!
- 死锁产生条件-不剥夺条件
- Mac MacBook Pro的移动硬盘方案
- kafka 削峰_从面试角度一文学完 Kafka
- .NET Core开发实战(第18课:日志框架:聊聊记日志的最佳姿势)--学习笔记(上)...
- 计算机控制用户自己编写什么软件吗,计算机控制软件技术基础.ppt
- atoi(s)函数用法
- lnmp mysql 自动关闭_mysql总是自动停止 日志提示Plugin ‘FEDERATED’ is disabled的解决办法...
- 个位数统计(java)
- 2018 年大疆机器学习算法工程师春季提前批笔试题
- 【从C到C++学习笔记】bool类型/const限定符/#define//结构体对齐
- WireGuard 教程:使用 DNS-SD 进行 NAT-to-NAT 穿透
- 西数发布首款消费级SSD:蓝盘、绿盘齐飞
- phpstorm运行php项目步骤
- PaddleOCR实现高精度车牌识别
- C语言实现url的编码和解码
- Android黄油计划之Choreographer原理解析
- 写一个在线位图字体制作工具!BitmapFont!
- 六、Spring Boot整合Shiro
- sheng的学习笔记-设计模式-代理模式