面试题答案
一键面试可能出现的问题
在多线程环境下,多个线程同时对ArrayList
进行添加元素和使用迭代器遍历操作时,可能会抛出ConcurrentModificationException
异常。这是因为当一个线程在遍历ArrayList
时,另一个线程对其进行了结构上的修改(如添加元素),导致迭代器感知到集合的结构发生了变化,从而抛出该异常。
解决方案 - 使用CopyOnWriteArrayList
CopyOnWriteArrayList
是Java并发包中提供的线程安全的List
实现。以下是使用CopyOnWriteArrayList
的代码示例:
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
// 启动添加元素的线程
Thread addThread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
list.add("Element " + i);
}
});
// 启动遍历的线程
Thread iterateThread = new Thread(() -> {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
});
addThread.start();
iterateThread.start();
try {
addThread.join();
iterateThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
CopyOnWriteArrayList的原理
- 写时复制:当对
CopyOnWriteArrayList
进行写操作(如添加、删除元素)时,它会先复制一份当前的数组,然后在新的数组上进行修改操作,最后将原数组引用指向新的数组。这样做可以保证在写操作时,读操作仍然可以基于原数组进行,不会受到写操作的影响。 - 迭代器:
CopyOnWriteArrayList
的迭代器是基于数组的快照创建的,在迭代过程中不会抛出ConcurrentModificationException
。因为迭代器遍历的是创建迭代器时数组的快照,而不是实时的数组,所以即使其他线程对数组进行了修改,迭代器也不会感知到,从而避免了异常的抛出。
综上所述,CopyOnWriteArrayList
通过写时复制的机制,提供了一种线程安全的List
实现,适用于读多写少的场景。