Java 集合框架04-fail-fast總結(jié)

      網(wǎng)友投稿 819 2022-05-30

      上一篇我們介紹了ArrayList的相關(guān)源碼,這篇我們將了解一下fail-fast機(jī)制的相關(guān)知識(shí)

      fail-fast的簡(jiǎn)介

      fail-fast的相關(guān)示例

      fail-fast的解決辦法

      fail-fast的原理

      解決fail-fast的原理

      fail-fast的簡(jiǎn)介

      fail-fast機(jī)制是java 集合的一種錯(cuò)誤機(jī)制。 當(dāng)多個(gè)線程對(duì)同一個(gè)集合的內(nèi)容進(jìn)行操作時(shí),就會(huì)產(chǎn)生fail-fast事件。

      例如:當(dāng)線程A通過(guò)iterator迭代器(或者 For和RandomAccess)來(lái)訪問(wèn)集合時(shí),線程B對(duì)集合的內(nèi)容進(jìn)行了修改,則線程A在訪問(wèn)集合時(shí)就會(huì)拋出ConcurrentModificationException異常,產(chǎn)生fail-fast事件。

      fail-fast的相關(guān)示例

      package com.jay.collection; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Created by xiang.wei on 2018/3/4 * * @author xiang.wei */ public class FailFastTest { /** * */ private static List globalList = new ArrayList(); /** * 線程one,two,three同時(shí)啟動(dòng),線程one向globalList中添加元素0,1,2,3,4,5,然后遍歷打印 * 線程two 與此同時(shí)也向globalList中添加元素10,11,12,13,14,15,然后遍歷打印, * 線程three 同時(shí)也在移除globalList中元素0,1,2,3,4,5,然后遍歷打印 * */ public static void main(String[] args) { new ThreadOne().start(); new ThreadTwo().start(); new ThreadThree().start(); } /** * 向globalList中添加元素0,1,2,3,4,5,然后遍歷打印 */ private static class ThreadOne extends Thread { @Override public void run() { for (int i = 0; i < 6; i++) { globalList.add(String.valueOf(i)); printAll(globalList); } } } /** * 向globalList中添加元素10,11,12,13,14,15,然后遍歷打印 */ private static class ThreadTwo extends Thread { @Override public void run() { for (int i = 10; i < 16; i++) { globalList.add(String.valueOf(i)); printAll(globalList); } } } /** * 移除globalList中元素0,1,2,3,4,5,然后遍歷打印 */ private static class ThreadThree extends Thread { @Override public void run() { for (int i = 0; i < 6; i++) { globalList.remove(String.valueOf(i)); printAll(globalList); } } } private static void printAll(List testList) { Iterator testIter = testList.iterator(); while (testIter.hasNext()) { System.out.println((testIter.next())); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      Java 集合框架04-fail-fast總結(jié)

      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

      fail-fast的解決辦法

      按照J(rèn)ava api文檔的建議,在多線程環(huán)境中我們需要選用java.util.concurrent包下的CopyOnWriteArrayList集合,

      即將

      private static List globalList = new ArrayList();

      1

      替換成

      private static List globalList = new CopyOnWriteArrayList();

      1

      fail-fast的原理

      我們此處以ArrayList為例,其Iterator的實(shí)現(xiàn)是在AbstractList中

      private class Itr implements Iterator { int cursor = 0; 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]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }

      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

      首先,定義一個(gè)實(shí)例變量

      protected transient int modCount = 0;

      1

      2

      當(dāng)實(shí)例化一個(gè)迭代器Itr時(shí),會(huì)將modCount的值賦給expectedModCount,以后每次迭代時(shí)都會(huì)檢查這兩個(gè)值是否相等,如果不相等則會(huì)拋出ConcurrentModificationException。顯然,expectedModCount不會(huì)改變,那么哪些操作會(huì)修改modCount的值呢?

      (ps: 這也解釋了為啥iterator為啥可以直接移除當(dāng)前元素)

      public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { //增加modCount的值 modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } public E remove(int index) { rangeCheck(index); //增加modCount的值 modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; }

      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

      從上述源碼中我們可以看出 add,remove方法修改modCount的值。

      解決fail-fast的原理

      我們接著看看CopyOnWriteArrayList是如何解決fail-fast的問(wèn)題的。

      首先CopyOnWriteArrayList的定義

      public class CopyOnWriteArrayList implements List, RandomAccess, Cloneable, java.io.Serializable {}

      1

      2

      CopyOnWriteArrayList直接實(shí)現(xiàn)了List,其iterator的迭代器COWIterator是在自身類實(shí)現(xiàn)的。

      static final class COWIterator implements ListIterator { private final Object[] snapshot; /** Index of element to be returned by subsequent call to next. */ private int cursor; private COWIterator(Object[] elements, int initialCursor) { cursor = initialCursor; snapshot = elements; } public boolean hasNext() { return cursor < snapshot.length; } public boolean hasPrevious() { return cursor > 0; } @SuppressWarnings("unchecked") public E next() { if (! hasNext()) throw new NoSuchElementException(); return (E) snapshot[cursor++]; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      (01) 和ArrayList繼承于AbstractList不同,CopyOnWriteArrayList沒(méi)有繼承于AbstractList,它僅僅只是實(shí)現(xiàn)了List接口。

      (02) ArrayList的iterator()函數(shù)返回的Iterator是在AbstractList中實(shí)現(xiàn)的;而CopyOnWriteArrayList是自己實(shí)現(xiàn)Iterator。

      (03) ArrayList的Iterator實(shí)現(xiàn)類中調(diào)用next()時(shí),會(huì)“調(diào)用checkForComodification()比較‘expectedModCount’和‘modCount’的大小”;但是,CopyOnWriteArrayList的Iterator實(shí)現(xiàn)類中,沒(méi)有所謂的checkForComodification(),更不會(huì)拋出ConcurrentModificationException異常!

      引用

      http://www.cnblogs.com/skywang12345/p/3308762.html

      Java 任務(wù)調(diào)度

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:CSS使用集群快照跨region復(fù)制指導(dǎo)
      下一篇:Hive RuntimeFilter
      相關(guān)文章
      久久99国产亚洲高清观看首页 | 夜色阁亚洲一区二区三区| 亚洲欧洲日本在线观看| 亚洲女同成人AⅤ人片在线观看| 伊人久久大香线蕉亚洲| 久久久无码精品亚洲日韩按摩| 亚洲av无一区二区三区| 午夜亚洲国产理论秋霞| 久久亚洲精品11p| 亚洲国产精品久久人人爱| 国产成人精品曰本亚洲79ren| 亚洲精品一二三区| 亚洲kkk4444在线观看| 亚洲AV永久无码区成人网站| 亚洲 自拍 另类小说综合图区 | 国产亚洲蜜芽精品久久| 亚洲影视一区二区| 亚洲人成影院在线无码按摩店| 亚洲av无码兔费综合| 激情无码亚洲一区二区三区 | 国产偷国产偷亚洲清高APP| 鲁死你资源站亚洲av| 亚洲成a人片在线播放| 国产成人亚洲影院在线观看| 国产亚洲情侣一区二区无码AV| 亚洲情综合五月天| 亚洲精品国产V片在线观看| 亚洲真人日本在线| 亚洲精品国产精品乱码不卡√| 亚洲AV日韩AV永久无码下载| 久久夜色精品国产噜噜亚洲AV| 亚洲欧洲国产综合| 男人天堂2018亚洲男人天堂| 亚洲精品国产av成拍色拍| 亚洲国产综合第一精品小说| 亚洲乱码一区二区三区国产精品| 亚洲欧洲无码AV不卡在线| 国产精品亚洲一区二区麻豆| 亚洲av纯肉无码精品动漫| 亚洲一区二区精品视频| 在线亚洲午夜理论AV大片|