失败安全迭代器

时间:2017-08-16 04:36:14

标签: java iterator concurrenthashmap

我对故障安全Iterator的了解是,它创建了原始数据结构的副本并对其进行迭代以允许并发修改。 我有一些困惑,如:

  1. 如何将修改反映回原始数据结构?
  2. 如果我们有两个主题:  线程A:迭代器1删除一个元素(元素A)  线程B:迭代器2已经开始迭代。如何将这个迭代器传达给原始DS已经改变。

3 个答案:

答案 0 :(得分:1)

正如您已经知道"故障安全"迭代器适用于原始集合的克隆副本。说明:

  1. 如何将修改反映回原始数据结构?

    如果在迭代时修改集合,则更改发生在原始副本而不是克隆副本(用于迭代)。因此,当前克隆拷贝的结构是完整的。见下文:

    public class FailSafeIteratorExample {
        public static void main(String[] args) {
            // Creating a ConcurrentHashMap
    
    
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();
        // Adding elements to map
        map.put("abc", 1);
    
        // Here, we are working on clone copy.
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()) {
            String key = (String) it.next();
            System.out.println(key + " : " + map.get(key));
            map.put("mno", 2); // This will not be reflected in the Iterator
        }
        System.out.println("\n\n");
    
        // Another clone copy just created with latest changes.
        // This will print the existing element with newly added element("mno")
        it = map.keySet().iterator();
        while (it.hasNext()) {
            String key = (String) it.next();
            System.out.println(key + " : " + map.get(key));
    
        }
    }}
    
  2. 在第一次迭代收集时,我们插入了一个新条目&#34; mno&#34;它没有反映在克隆的副本中。但是当我们第二次迭代它时,另一个克隆的副本是从原始集合中创建的,该集合具有这个新添加的条目&#34; mno&#34;因此,它被打印出来。

    1. 主题: 当单个线程在克隆副本上工作时修改集合时,无法进行通信。他们不知道其他线程对原始副本所做的更改。
    2. 希望这有帮助!

答案 1 :(得分:0)

Fail Safe Iterator:

Fail Safe Iterator复制内部数据结构(对象数组)并迭代复制的数据结构。对迭代器进行的任何结构修改都会影响复制的数据结构。因此,原始数据结构在结构上保持不变。因此,失败安全迭代器不会抛出ConcurrentModificationException。

与Fail Safe Iterator相关的两个问题是:

  1. 维护复制的数据结构即内存的开销。

  2. 故障安全迭代器不保证正在读取的数据是当前原始数据结构中的数据。

  3. 根据Oracle文档,失败安全迭代器通常成本太高,但当遍历操作大大超过突变时可能比替代方法更有效,并且当您不能或不想同步遍历但需要排除干扰时非常有用并发线程之间。 “快照”样式迭代器方法在创建迭代器时使用对数组状态的引用。此数组在迭代器的生命周期内永远不会更改,因此无法进行干扰,并且保证迭代器不会抛出ConcurrentModificationException。迭代器将不会反映自创建迭代器以来对列表的添加,删除或更改。不支持迭代器本身的元素更改操作(remove(),set()和add())。这些方法抛出UnsupportedOperationException。

答案 2 :(得分:-1)

  1. 您无法修改要迭代的集合(concurent修改)。如果您修改集合中的对象,它们也会在原始集合中进行修改。

  2. 不会传达。你正在迭代一个副本。如果您尝试修改集合,请参阅1.