如果故障安全迭代器创建了一个单独的副本并对其进行处理,那么它怎么知道对原始文件所做的任何更改?
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");
}
}
输出结果为:
pujan1
manish1
swati1
答案 0 :(得分:13)
在Java中没有“故障安全”迭代器这样的东西。至少,Java SE规范没有定义这样的术语。因此,我建议您避免使用术语“故障安全”来描述Java迭代器。
我很清楚互联网上和Stack Overflow上其他地方的各种文章都使用“故障安全”一词,但它们的使用并不是确定的,而且可能是错误的,或者至少是误导性的。我相信你被这些文件误导了。
听起来你在某处看到“故障安全”迭代器在单独的副本上工作。在您的示例中,您使用ConcurrentHashMap
,它确实具有非故障快速的迭代器。但是,CHM的迭代器不能在副本上运行。相反,它们具有官方规范描述为weakly consistent的语义。这个定义有些深奥,但实质上,这种迭代器报告的任何元素都保证在某个时间点存在于集合中。这些迭代器可能会也可能不会反映迭代开始后对集合所做的更改。这就是运行迭代器的线程看到另一个线程所做的更改的原因。 (也可以看到一些或没有变化可见,因为这些线程有数据竞争。)
其迭代器不是快速失败的另一个集合的示例是CopyOnWriteArrayList。此集合的迭代器在快照上运行,因此对集合的任何后续更改都是从不通过迭代器可见。
为了完整性,这里是ArrayList
规范中fail-fast迭代器的定义。 Java中的大多数其他(非并发)集合都具有类似定义的快速失败迭代策略。