java中fail-fast 和 fail-safe的區別

首先要弄明白同步修改的概念,指的是一個或者多個線程正在遍歷一個集合,此時另外一個線程修改了Collection的數據結構(添加,刪除或者修改);java

1.fail-fast機制spring

fail-fast機制在集合被遍歷時,若是集合元素被修改,直接拋出Concurrent Modification Exception,有兩種狀況;springboot

1>單線程環境下數據結構

集合被建立後,在遍歷它的過程當中修改告終構。注意 remove()方法會讓expectModcount和modcount 相等,因此是不會拋出這個異常。多線程

2>多線程環境下this

一個線程在遍歷元素時,另外一個線程對元素進行了修改線程

fail-fast機制校驗的原理是內部維護了一個標識「mode」,當集合數據結構被修改時,修改mode;在每次遍歷的next和hasNext方法會去檢驗「mode」是否被修改,若修改則拋出Concurrent Modification Exceptioncode

例如ArrayList迭代部分的源碼對象

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
        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 {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

2.fail-safe機制element

fail-safe機制在每次對集合進行修改時會複製一個新的對象,所以不會拋出ConcurrentModificationException,

fail-safe機制有兩個問題

(1)須要複製集合,產生大量的無效對象,開銷大

(2)沒法保證讀取的數據是目前原始數據結構中的數據。

3.fail-fast和fail-safe機制例子

package com.example.springbootDemo.service;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class FailFastExample {
    public static void main(String[] args) {
        Map<String,String> premiumPhone = new HashMap<String,String>();
        premiumPhone.put("Apple", "iPhone");
        premiumPhone.put("HTC", "HTC one");
        premiumPhone.put("Samsung","S5");

        Iterator iterator = premiumPhone.keySet().iterator();

        while (iterator.hasNext())
        {
            System.out.println(premiumPhone.get(iterator.next()));
            premiumPhone.put("Sony", "Xperia Z");
        }
    }
}
package com.example.springbootDemo.service;

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

public class FailSafeExample {
    public static void main(String[] args) {
        ConcurrentHashMap<String,String> premiumPhone =
                new ConcurrentHashMap<String,String>();
        premiumPhone.put("Apple", "iPhone");
        premiumPhone.put("HTC", "HTC one");
        premiumPhone.put("Samsung","S5");

        Iterator iterator = premiumPhone.keySet().iterator();

        while (iterator.hasNext())
        {
            System.out.println(premiumPhone.get(iterator.next()));
            premiumPhone.put("Sony", "Xperia Z");
        }
        System.out.printf("premiumPhone:"+premiumPhone.toString());
    }
}
相關文章
相關標籤/搜索