我是靠谱客的博主 饱满荔枝,这篇文章主要介绍java集合之failfast机制,现在分享给大家,希望可以做个参考。

failfast机制:快速失败机制。

是java类在应对并发访问在对集合进行迭代过程中,内部对象结构发生变化的一种保护措施,这种错误检测机制为这种有可能发生错误,通过抛出ConcurrentModificationException,防止迭代过程中读到脏数据。

以ArrayList为例:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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循环:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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); } } }

结果:会抛出并发修改异常,也是不对的。
在这里插入图片描述

使用迭代器:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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机制内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(75)

评论列表共有 0 条评论

立即
投稿
返回
顶部