本篇是关于Java基础的内容,老鸟可以直接略过。新手的话,可以看看,当一个知识点查漏补缺。
1.关于多线程操作同一个List的代码
package com.cjt.demo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author caojiangtao
* @date 2020-07-20 10:34
*/
public class TestFailFast {
/**
* java.util包中的所有集合类,包括List<E>,Set<E>,Map<K,V>都是被设计为fail-fast的,而java.util.concurrent中的集合类都为fail-safe的。
*
* 概念:fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。
*
* 集合的并发修改异常 --<ConcurrentModificationException>
* fail—fast迭代器抛出ConcurrentModificationException
* fail—safe迭代器从不抛出ConcurrentModificationException
*
* **/
/** 多线程操作ArrayList的时候,会报错 java.util.ConcurrentModificationException **/
// public static List<String> list = new ArrayList<>();
/** 多线程操作的时候使用CopyOnWriteArrayList是安全的,不会报错 **/
public static List<String> list = new CopyOnWriteArrayList<>();
public static void main(String[] args) {
new ThreadOne().start();
new ThreadTwo().start();
}
private static void printAll(String flag) {
String val = null;
Iterator<String> it = list.iterator();
while(it.hasNext()) {
val = it.next();
System.out.println("flag = "+flag+", val == "+val);
}
}
public static class ThreadOne extends Thread {
@Override
public void run() {
for(int i = 0 ; i < 6 ; i++) {
list.add("线程1测试 ************************ "+i);
printAll("** thread-1 ** "+i);
}
}
}
public static class ThreadTwo extends Thread {
@Override
public void run() {
for(int i = 0 ; i < 6 ; i++) {
list.add("线程2测试 ================= "+i);
printAll("## thread-2 ## "+i);
}
}
}
}
这段代码中List初始化的时候有两种方式,
- List<String> list = new ArrayList<>();
- List<String> list = new CopyOnWriteArrayList<>();
如果使用第一种ArrayList<> 的话,一定会抛出异常ConcurrentModifificationException,使用CopyOnWriteArrayList<>就一定不会抛出该异常。这个异常翻译过来就是“并发修改异常”,也就是说List的子类ArrayList不支持并发修改。
2.关于并发修改异常fail-fast和fail-safe
- java.util 包下的集合,在实现的时候,如果有多个线程同时操作同一个集合的并发操作,会快速的失败,也就是我们常说的fail-fast,然后接着抛出ConcurrentModifificationException。
- java.util.concurrent 包下的集合,在实现的时候,允许多线程操作同一个集合,而且不会抛出ConcurrentModifificationException,也就是我们常说的 fail-safe。ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet等这类就属于fail-safe,不会抛出ConcurrentModifificationException。