代码演示:
public class NoSafeDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); for (int i = 0; i < 30; i++) { new Thread(() -> { list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); },String.valueOf(i)).start(); } } }
故障现象 java.util.ConcurrentModificationException Java并发修改异常
解决方案
使用 Vector
public class NoSafeDemo { public static void main(String[] args) { // List<String> list = new ArrayList<>(); List<String> list = new Vector<>(); for (int i = 0; i < 30; i++) { new Thread(() -> { list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); },String.valueOf(i)).start(); } } }
2. 使用线程安全的 list 集合 (用集合的工具类)
public class NoSafeDemo { public static void main(String[] args) { // List<String> list = new Vector<>(); List<String> noSafelist = new ArrayList<>(); List<String> list = Collections.synchronizedList(noSafelist); for (int i = 0; i < 30; i++) { new Thread(() -> { list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); },String.valueOf(i)).start(); } } }
3.写实复制 使用 CopyOnWrite
public class NoSafeDemo { public static void main(String[] args) { // List<String> list = new Vector<>(); // List<String> noSafelist = new ArrayList<>(); // List<String> list = Collections.synchronizedList(noSafelist); List<String> list = new CopyOnWriteArrayList<>(); for (int i = 0; i < 30; i++) { new Thread(() -> { list.add(UUID.randomUUID().toString().substring(0,8)); System.out.println(list); },String.valueOf(i)).start(); } } }
解释:
使用 Vector 实则是在 add 的方法上加了 synchronized , 很好想,这样会影响性能。
public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }
写实复制:CopyOnWrite 容器即写实复制的容器。往一个容器中添加元素的时候,不直接往当前容器Object[] 添加,而是先将当前容器 Object[] 进行 Copy,复制出一个新的容器 Object[] newElements,然后新的容器 Object[] newElements 里添加元素,添加元素之后,再将原容器的引用指向新的容器 setArray(newElements);这样做的好处是可以对 CopyOnWrite 容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以 CopyOnWrite 容器也是一种读写分离的思想,读和写不同的容器。
CopyOnWritede add方法的源代码:
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(); } }
同上 HashSet 线程不安全 有 Set set = new CopyOnWriteArraySet<>(); 是线程安全的
HashMap 底层是什么
Node节点 Node链表 + 红黑树
new HashMap() 等价于 new HashMap(16,0.75)
HashMap 扩容是原来容量 * 2
原文:https://www.cnblogs.com/lililixuefei/p/13185941.html