我很少ArrayList<T>
包含用户定义的对象(例如 List<Student>, List<Teachers>
)。这些对象本质上是不可变的,即没有提供 setter ——而且,由于问题的性质,“没有人”会尝试修改这些对象。一旦填充了“ArrayList”,就不允许/不可能进一步添加/删除对象。所以List不会动态变化。
在这样给定的条件下,这个数据结构(即 ArraList
)能否被多线程(同时)安全使用?每个线程只会读取对象属性,但不可能进行“设置”操作。
所以,我的问题是我可以依赖 ArrayList
?如果不是,在这种情况下可以使用哪些其他更便宜的数据结构?
最佳答案
您可以在线程之间共享任何对象或数据结构,前提是它们在安全发布 后从未被修改过。如评论中所述,初始化 ArrayList
的写入与其他线程获取引用的读取之间必须存在 * happen-before* 关系。
例如如果您在启动其他线程之前或在将处理列表的任务提交给 ExecutorService
之前完全设置了 ArrayList
,那么您是安全的。
如果线程已经在运行,您必须使用一种线程安全机制将 ArrayList
引用移交给其他线程,例如通过将其放入 BlockingQueue
。
即使是最简单的形式,如将引用存储到 static final
或 volatile
字段中也可以。
请记住,事后永不修改对象的先决条件必须始终成立。建议通过使用 Collections.unmodifiableList(…)
包装列表来强制执行该约束。并在发布前忘记原始列表引用:
class Example {
public static final List<String> THREAD_SAFE_LIST;
static {
ArrayList<String> list=new ArrayList<>();
// do the setup
THREAD_SAFE_LIST=Collections.unmodifiableList(list);
}
}
或
class Example {
public static final List<String> THREAD_SAFE_LIST
=Collections.unmodifiableList(Arrays.asList("foo", "bar"));
}
关于java - ArrayList 可以在多线程环境中用于只读目的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21714886/