【问题标题】:Is Enumeration in java is Fail-safe? if yes how?java中的枚举是故障安全的吗?如果是的话怎么办?
【发布时间】:2017-10-29 07:59:34
【问题描述】:

java 中有故障安全迭代器,它创建集合的副本以进行迭代以提供故障安全行为。

枚举适用于遗留 Java 类 Vector、Stack 和 HashTable 等(这些是同步集合)。

Java 中的枚举如何实现故障安全,它如何提供故障安全行为? 它是否也为迭代创建了集合的副本?

【问题讨论】:

  • 您所说的“故障安全”是什么意思?
  • Like CouncurrentHashMap 迭代器是故障安全的,因为它创建了一个集合对象的副本以进行迭代,因此如果另一个线程试图改变集合对象的结构(通过添加或删除一个元素)它不会干扰迭代器。类似地,枚举也是一个故障安全迭代器,但它如何提供故障安全行为在这里受到质疑。
  • “枚举是故障安全的”语句的来源是什么?它不是,所以“为什么它是故障安全”的问题不适用。

标签: java enumeration


【解决方案1】:

我不会调用 Enumeration 故障安全。

至少不是Vectorelements()方法返回的实现:

public Enumeration<E> elements() {
    return new Enumeration<E>() {
        int count = 0;

        public boolean hasMoreElements() {
            return count < elementCount;
        }

        public E nextElement() {
            synchronized (Vector.this) {
                if (count < elementCount) {
                    return elementData(count++);
                }
            }
            throw new NoSuchElementException("Vector Enumeration");
        }
    };
}

如果您在迭代 Vector 时对其进行修改,则此实现可能会导致不良行为而不会引发异常。

例如,以下代码将导致无限循环,其中每次调用els.nextElement () 都会返回相同的元素"a"

Vector<String> vec = new Vector<> ();
vec.add ("a");
vec.add ("b");
vec.add ("c");
Enumeration<String> els = vec.elements ();
while (els.hasMoreElements ()) {
    System.out.println (els.nextElement ());
    vec.add (0,"d");
}

【讨论】:

  • 这是否意味着即使在并发修改的情况下也不会出现任何异常。我们可以说它既不是快速故障也不是故障安全(就多线程环境中的并发修改而言)。
  • @AnshulSharma 没错,除非您在调用hasMoreElements() 和调用nextElement() 之间调用Vectorremove(),这可能会导致nextElement() 抛出NoSuchElementException .
  • 感谢@Eran,这很有帮助。
猜你喜欢
  • 2013-06-26
  • 1970-01-01
  • 1970-01-01
  • 2011-07-20
  • 1970-01-01
  • 2016-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多