本文内容大多基于官方文档和网上前辈经验总结,经过个人实践加以整理积累,仅供参考。
fail-safe 机制保证任何对集合结构的修改都会在一个复制的集合上进行,因此不会抛出 java.util.ConcurrentModificationException 异常。
fail-safe机制产生的两个问题:
(1) 复制集合会产生大量临时对象,增加系统开销
(2) 无法保证读取的数据是目前原始数据结构中的数据
与 fail-safe 机制对应的是 fail-fast 机制
fail-safe 示例
(1) 单线程
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import org.junit.Test;
public class FailSafeTest {
@Test
public void test() {
ConcurrentHashMap<String, String> phones = new ConcurrentHashMap<>();
phones.put("Apple", "iPhone");
phones.put("Samsung", "Galaxy");
phones.put("Moto", "Z Play");
Iterator<String> iterator = phones.keySet().iterator();
while (iterator.hasNext()) {
System.out.println(phones.get(iterator.next()));
phones.put("Smartisan", "M1L");
}
}
}
运行测试结果:
(2) 多线程
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class FailSafeTest {
private static List<Integer> list = new CopyOnWriteArrayList<>();
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
list.add(i);
}
new ThreadOne().start();
new ThreadTwo().start();
}
private static class ThreadOne extends Thread {
@Override
public void run() {
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class ThreadTwo extends Thread {
@Override
public void run() {
for (int i = 9; i >= 0; i--) {
list.remove(i);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
运行测试结果: