【发布时间】:2014-12-12 03:25:40
【问题描述】:
我有一个EnumSet,它是最终的且不可变的,即在构造函数中初始化一次。
这个EnumSet 线程上的contains() 方法安全吗?它在内部使用迭代器进行包含检查。因此,如果两个线程同时调用contains(),一个调用中的迭代器位置会影响另一个吗?还是迭代器在这两个线程调用中有不同的实例?
【问题讨论】:
标签: java collections thread-safety enumset
我有一个EnumSet,它是最终的且不可变的,即在构造函数中初始化一次。
这个EnumSet 线程上的contains() 方法安全吗?它在内部使用迭代器进行包含检查。因此,如果两个线程同时调用contains(),一个调用中的迭代器位置会影响另一个吗?还是迭代器在这两个线程调用中有不同的实例?
【问题讨论】:
标签: java collections thread-safety enumset
EnumSet 的 内容 可以更改,尽管对它的 reference 是最终的。不,EnumSet 是不可变的。但是,您可以通过 Collections.unmodifiableSet() 包装您的 EnumSet。如果您还避免保留对原始 EnumSet 的任何引用,则不可修改的包装对象在功能上是不可变的。
尽管存在可变性,但只要不修改 Set,两个迭代器同时在同一个 Set 上运行就不会出现问题。这与只有一个迭代器的情况并没有什么不同。
无论如何,EnumSet 的 contains() 方法可能不会创建或使用迭代器。该类通过位向量实现成员资格,因此它使用位操作来执行contains() 测试。
【讨论】:
不,如果两个线程同时调用contains(),那将调用iterator() 两次,这将创建两个单独的迭代器。
如果您试图在两个线程之间共享一个迭代器,那将不是一个好主意。
请注意,如果您在一个线程中修改集合,同时在另一个线程中对其进行迭代(例如,通过contains),那么文档的这一位就会发挥作用:
返回的迭代器是弱一致的:它永远不会抛出 ConcurrentModificationException 并且它可能会或可能不会显示在迭代过程中对集合进行的任何修改的影响。
【讨论】: