标签:iterator his 操作 ring arraylist zed tor val exp
底层:Object数组,非线程安全
默认容量:10,其实是0,第一次add时,才会主动去扩容
每一扩容,变为原来容量的1.5倍。10->15->22
/* */ private void grow(int minCapacity)
/* */ {
/* 254 */ int oldCapacity = elementData.length;
/* 255 */ int newCapacity = oldCapacity + (oldCapacity >> 1);
/* 256 */ if (newCapacity - minCapacity < 0)
/* 257 */ newCapacity = minCapacity;
/* 258 */ if (newCapacity - 2147483639 > 0) {
/* 259 */ newCapacity = hugeCapacity(minCapacity);
/* */ }
/* 261 */ elementData = Arrays.copyOf(elementData, newCapacity);
/* */ }
非线程安全的case:ConcurrentModificationException
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
for (int i = 0; i < 30; i++) {
Thread thread = new Thread(() -> {
list.add(UUID.randomUUID().toString());
System.out.println(list);
});
thread.start();
}
}
为什么会报错:遍历ArrayList时,另一线程执行add操作,会造成modCount变化,fail-fast思想
*/ final void checkForComodification() {
/* 900 */ if (modCount != expectedModCount) {
/* 901 */ throw new ConcurrentModificationException();
/* */ }
/* */ }
Exception in thread "Thread-25" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at java.util.AbstractCollection.toString(AbstractCollection.java:461)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at com.hashmapt.ArrayListTest.lambda$0(ArrayListTest.java:29)
at java.lang.Thread.run(Thread.java:745)
[82b9f5c7-7c17-48a1-87e0-e1ff90e084bb, fd427bbf-6adf-45af-b806-5af9a044d6d7]
[82b9f5c7-7c17-48a1-87e0-e1ff90e084bb, fd427bbf-6adf-45af-b806-5af9a044d6d7, 96f5bb81-c50b-441b-9833-e81c364b3c5f, c4894981-260b-4b7b-8076-168703f7e8ba]
[82b9f5c7-7c17-48a1-87e0-e1ff90e084bb, fd427bbf-6adf-45af-b806-5af9a044d6d7, 96f5bb81-c50b-441b-9833-e81c364b3c5f, c4894981-260b-4b7b-8076-168703f7e8ba, c201001b-41a8-4919-ad5f-5e36bd86a56b]
[82b9f5c7-7c17-48a1-87e0-e1ff90e084bb, fd427bbf-6adf-45af-b806-5af9a044d6d7, 96f5bb81-c50b-441b-9833-e81c364b3c5f]
[82b9f5c7-7c17-48a1-87e0-e1ff90e084bb, fd427bbf-6adf-45af-b806-5af9a044d6d7, 96f5bb81-c50b-441b-9833-e81c364b3c5f, c4894981-260b-4b7b-8076-168703f7e8ba, c201001b-41a8-4919-ad5f-5e36bd86a56b, a492afac-264b-4111-9876-3e0e01b606db, 48dcca36-b425-451e-ab8b-1ad0967bfa91]
[82b9f5c7-7c17-48a1-87e0-e1ff90e084bb, fd427bbf-6adf-45af-b806-5af9a044d6d7, 96f5bb81-c50b-441b-9833-e81c364b3c5f, c4894981-260b-4b7b-8076-168703f7e8ba, c201001b-41a8-4919-ad5f-5e36bd86a56b, a492afac-264b-4111-9876-3e0e01b606db, 48dcca36-b425-451e-ab8b-1ad0967bfa91, 65c3cb2c-b4d4-4b59-ad2a-0c2194733d58]
[82b9f5c7-7c17-48a1-87e0-e1ff90e084bb, fd427bbf-6adf-45af-b806-5af9a044d6d7, 96f5bb81-c50b-441b-9833-e81c364b3c5f, c4894981-260b-4b7b-8076-168703f7e8ba, c201001b-41a8-4919-ad5f-5e36bd86a56b, a492afac-264b-4111-9876-3e0e01b606db, 48dcca36-b425-451e-ab8b-1ad0967bfa91, 65c3cb2c-b4d4-4b59-ad2a-0c2194733d58, 80dca1e1-c3bb-4b70-9cbd-f3ebfb699093]
[82b9f5c7-7c17-48a1-87e0-e1ff90e084bb, fd427bbf-6adf-45af-b806-5af9a044d6d7]
[82b9f5c7-7c17-48a1-87e0-e1ff90e084bb, fd427bbf-6adf-45af-b806-5af9a044d6d7, 9
public static void main(String[] args) {
// List<String> list = new ArrayList<String>();
List<String> list = new Vector<String>();
for (int i = 0; i < 30; i++) {
Thread thread = new Thread(() -> {
list.add(UUID.randomUUID().toString());
System.out.println(list);
});
thread.start();
}
}
Vector是线程安全的容器,原理是对add,remove,iterator等所有方法都加synchronized锁
/* */ public synchronized boolean add(E e)
/* */ {
/* 781 */ modCount += 1;
/* 782 */ ensureCapacityHelper(elementCount + 1);
/* 783 */ elementData[(elementCount++)] = e;
/* 784 */ return true;
/* */ }
此容器虽然线程安全,但是效率极低,使用场景很少
public static void main(String[] args) {
// List<String> list = new ArrayList<String>();
// List<String> list = new Vector<String>();
List<String> list = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < 30; i++) {
Thread thread = new Thread(() -> {
list.add(UUID.randomUUID().toString());
System.out.println(list);
});
thread.start();
}
}
其原理同Vector,对所有操作加synchronized锁
public static void main(String[] args) {
// List<String> list = new ArrayList<String>();
// List<String> list = new Vector<String>();
// List<String> list = Collections.synchronizedList(new ArrayList<>());
List<String> list = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 30; i++) {
Thread thread = new Thread(() -> {
list.add(UUID.randomUUID().toString());
System.out.println(list);
});
thread.start();
}
}
原理:写时复制,即只对add操作加锁,读操作不加锁。
add时,拷贝一份副本到内存,扩容后,将array指针指向新的数组
/* */ public boolean add(E e)
/* */ {
/* 434 */ ReentrantLock lock = this.lock;
/* 435 */ lock.lock();
/* */ try {
/* 437 */ Object[] elements = getArray();
/* 438 */ int len = elements.length;
/* 439 */ Object[] newElements = Arrays.copyOf(elements, len + 1);
/* 440 */ newElements[len] = e;
/* 441 */ setArray(newElements);
/* 442 */ return true;
/* */ } finally {
/* 444 */ lock.unlock();
/* */ }
/* */ }
此博客详细介绍了CopyOnWrite的使用场景及优缺点
JDK1.8 CopyOnWriteArrayList源码学习
标签:iterator his 操作 ring arraylist zed tor val exp
原文地址:https://www.cnblogs.com/lt123/p/13289146.html