如果Collection只写在构造函数中,那么它是一个线程安全吗?

假设我们有这门课

final class Foo { private final Set bar = new HashSet(); public Foo() { bar.add("one"); bar.add("two"); bar.add("three"); } public boolean contains(final String s) { return bar.contains(s); } } 

将实例化Foo并从多个线程调用contains此对象是不是线程安全的?

  1. 对该集合的引用是privatefinal 。 没有人可以直接访问该集合。
  2. 唯一的写访问权限发生在构造函数中
  3. 执行构造函数后,集合将只读取而不是修改。

如果没有,是否有一个纯Java替代Guava的不可变集合?

它是线程安全的

1)构造函数在完全构造之前不会泄漏引用。

2)没有人有任何方法可以访问该集合。

3)不能创建可以编辑集合的子类。

但是作为一般规则,如果你想实现这个使用来自guava的不可变集合,那么这个行为对程序员来说是显而易见的,然后返回整个映射是安全的。 我认为在纯java中你可以返回一个不可修改的集合视图。

你的Foobar实际上是不可变的。 它是线程安全的。

这取决于如何发布对此对象的访问权限。 虽然bar Set是最终的,因此保证所有线程都可见,但是在构造函数结束之前不能保证映射的数量。

但是,无论对象是如何创建和提供的,都可以保证它是线程安全的。

 private final Set bar; public Foo() { bar = new HashSet(Arrays.asList("one", "two", "three")); } 

测试最终字段的初始化安全性

https://stackoverflow.com/a/23995782/676877

只要以只读方式访问,我认为您应该是安全的。 此外,java提供了通过Collections类上的静态方法公开的基本集合的不可变版本,因此我将查看Collections.unmodifiableSet()

此外,当您在示例中添加字符串,并且字符串本身在java中是不可变的时,如果添加了可变对象然后决定从不同的线程修改/读取它们,则会遇到麻烦(在这种情况下您需要同步块)。