故障安全迭代器的逻辑是什么?

puj*_*ain 9 java collections iterator

如果故障安全迭代器创建一个单独的副本并对其进行处理,那么它如何知道对原始文件所做的任何更改?

public class concurrentHashMap {
    public static void main(String[] args) throws InterruptedException {
        MapCheck obj1 = new MapCheck();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                obj1.put();
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                obj1.iterte();
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

class MapCheck {
    Map<Integer,String> map = new ConcurrentHashMap<>();
    {
        map.put(1, "pujan");
        map.put(2, "manish");
        map.put(3, "swati");
    }

    void iterte() throws InterruptedException {
        for (int key : map.keySet()) {
            Thread.sleep(2000);
            System.out.println(map.get(key));
        }
    }

    void put() throws InterruptedException{
        Thread.sleep(2000);
        map.put(1, "pujan1");
        map.put(2, "manish1");
        map.put(3, "swati1");
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

pujan1
manish1
swati1
Run Code Online (Sandbox Code Playgroud)

Stu*_*rks 13

在Java中没有"故障安全"迭代器这样的东西.至少,Java SE规范没有定义这样的术语.因此,我建议您避免使用术语"故障安全"来描述Java迭代器.

我很清楚,因特网上和Stack Overflow其他地方的各种文章都使用了"故障安全"这个术语,但它们的使用并不是确定的,而且可能是错误的,或者至少是误导性的.我相信你被这些文件误导了.

听起来你在某处读到"故障安全"迭代器在单独的副本上工作.在您的示例中,您使用的是a ConcurrentHashMap,它确实具有非故障快速的迭代器.但是,CHM的迭代器不能在副本上运行.相反,它们具有官方规范描述为弱一致的语义.这个定义有些深奥,但实质上,这种迭代器报告的任何元素都保证在某个时间点存在于集合中.这些迭代器可能会也可能不会反映迭代开始后对集合所做的更改.这就是运行迭代器的线程看到另一个线程所做的更改的原因.(由于这些线程有数据竞争,因此也可能会有一些或没有变化可见.)

其迭代器不是快速失败的另一个集合的示例是CopyOnWriteArrayList.此集合的迭代器在快照上运行,因此对集合的任何后续更改都不会通过迭代器显示.

为了完整起见,这里是规范中的故障快速迭代器的ArrayList定义.Java中的大多数其他(非并发)集合都具有类似定义的快速失败迭代策略.