我们知道,默认情况下迭代并发集合不是线程安全的,所以不能使用:
Set<E> set = Collections.synchronizedSet(new HashSet<>());
//fill with data
for (E e : set) {
process(e);
}
Run Code Online (Sandbox Code Playgroud)
这是因为在迭代期间可能会添加数据,因为没有排他锁set.
这在javadoc中描述Collections.synchronizedSet:
public static Set synchronizedSet(Set s)
返回由指定集支持的同步(线程安全)集.为了保证串行访问,必须通过返回的集完成对后备集的所有访问.
当迭代它时,用户必须手动同步返回的集合:
Set s = Collections.synchronizedSet(new HashSet());
...
synchronized (s) { Iterator i = s.iterator(); // Must be in the synchronized block while (i.hasNext()) foo(i.next()); }不遵循此建议可能会导致非确定性行为.
然而,这并不适用于Set.forEach,它继承了默认的方法forEach从Iterable.forEach.
现在我查看了源代码,在这里我们可以看到我们有以下结构:
Collections.synchronizedSet().我们得到一个:
public static <T> Set<T> synchronizedSet(Set<T> s) {
return new SynchronizedSet<>(s); …Run Code Online (Sandbox Code Playgroud)