在多线程环境下,可通过以下几种方式避免快速失败(Fail-Fast)异常:
1. 使用线程安全的集合类
Java 提供了多种线程安全的集合类,它们在迭代时不会抛出 ConcurrentModificationException
。
示例:使用 CopyOnWriteArrayList
java
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteExample {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
list.add("apple");
list.add("banana");
// 线程 1:遍历集合
Thread t1 = new Thread(() -> {
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 线程 2:修改集合
Thread t2 = new Thread(() -> {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add("cherry"); // 不会触发异常
});
t1.start();
t2.start();
}
}
常用线程安全集合
CopyOnWriteArrayList
:适用于读多写少的场景,每次修改时会创建新数组。ConcurrentHashMap
:高效的线程安全 Map,支持并发读写。ConcurrentLinkedQueue
:无界线程安全队列,基于链表实现。
2. 使用同步机制
通过显式的同步(如 synchronized
块或 ReentrantLock
)来保证同一时间只有一个线程访问集合。
示例:使用 synchronized
块
java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SynchronizedListExample {
private static final List<String> list = new ArrayList<>();
private static final Object lock = new Object();
public static void main(String[] args) {
list.add("apple");
list.add("banana");
// 线程 1:遍历集合
Thread t1 = new Thread(() -> {
synchronized (lock) {
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
});
// 线程 2:修改集合
Thread t2 = new Thread(() -> {
synchronized (lock) {
list.add("cherry");
}
});
t1.start();
t2.start();
}
}
注意事项
- 同步会导致性能下降,尤其在读操作频繁时。
- 需要确保所有对集合的访问都使用相同的锁。
3. 使用 Collections.synchronizedList()
包装集合
将普通集合转换为同步集合,但迭代时仍需手动同步。
示例:
java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class SynchronizedWrapperExample {
public static void main(String[] args) {
List<String> list = Collections.synchronizedList(new ArrayList<>());
list.add("apple");
list.add("banana");
// 迭代时必须手动同步
synchronized (list) {
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
// 修改操作会自动同步
list.add("cherry");
}
}
4. 使用并发友好的迭代方式
某些并发集合提供了弱一致性(Weakly Consistent)的迭代器,允许在迭代过程中修改集合。
示例:ConcurrentHashMap
的弱一致性迭代器
java
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("apple", 1);
map.put("banana", 2);
// 弱一致性迭代器允许并发修改
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
System.out.println(key);
map.put("cherry", 3); // 不会抛出异常
}
}
}
根据具体业务场景选择合适的方案,优先考虑使用 Java 提供的并发集合类,避免手动同步带来的复杂性。