概述
failfast机制:快速失败机制。
是java类在应对并发访问在对集合进行迭代过程中,内部对象结构发生变化的一种保护措施,这种错误检测机制为这种有可能发生错误,通过抛出ConcurrentModificationException,防止迭代过程中读到脏数据。
以ArrayList为例:
public class Demo {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
new Thread(new MyRunnable1(arrayList)).start();
new Thread(new MyRunnable2(arrayList)).start();
}
/**
* 添加元素的线程
*/
private static class MyRunnable1 implements Runnable{
private ArrayList<String> arrayList;
public MyRunnable1(ArrayList<String> arrayList){
this.arrayList = arrayList;
}
@Override
public void run() {
arrayList.add("1");
arrayList.add("1");
try {
//睡眠1秒
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
arrayList.add("1");
arrayList.add("1");
arrayList.add("1");
arrayList.add("1");
}
}
/**
* 迭代获取元素的线程
*/
private static class MyRunnable2 implements Runnable{
private ArrayList<String> arrayList;
public MyRunnable2(ArrayList<String> arrayList){
this.arrayList = arrayList;
}
@Override
public void run() {
Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
}
//这段代码就会抛出该异常,因为在ArrayList对象的迭代过程中有新的线程对他进行了
并发修改。触发了快速失败机制。要用迭代器才会触发,普通的for循环不会触发(foreach会)。实际上是具有快速失败机制的迭代器。
//相应在array中的源码:
private class Itr implements Iterator<E> {
//游标,当前迭代元素下标
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
//创建该迭代器时会把该对象当前的modCount赋值给expectedModCount 。
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
//检查是否存在并发修改
final void checkForComodification() {
//假如另一个线程修改了该对象,modCount 值就会大于expectedModCount,然后抛出异常。
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
如何正确的在迭代过程中删除数据。
普通for循环:
public class Demo2 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0;i<5;i++){
list.add(5);
}
for (int i = 0;i<5;i++){
System.out.println(list.get(i));
list.remove(i);
}
}
}
结果:
会抛出越界异常,因为删除后,size变小了 但是循环还是5次,所以在循环第四次时就抛出了越界异常,这是不正确的。
使用foreach
public class Demo2 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0;i<5;i++){
list.add(5);
}
for (Integer item:list){
System.out.println(item);
list.remove(item);
}
}
}
结果:会抛出并发修改异常,也是不对的。
使用迭代器:
public class Demo2 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0;i<5;i++){
list.add(5);
}
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
Integer next = iterator.next();
System.out.println(next);
iterator.remove();
}
}
System.out.println(list.size());
}
结果:正确,数据也正常删除了。
总的来说failfast是比较当前修改次数和期望修改次数不一致时就会抛出异常。
最后
以上就是饱满荔枝为你收集整理的java集合之failfast机制的全部内容,希望文章能够帮你解决java集合之failfast机制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复