我很少ArrayList<T>
包含用户定义的对象(例如List<Student>, List<Teachers>
)。这些对象本质上是不可变的,即没有提供setter - 而且,由于问题的性质,“没有人”会试图修改这些对象。填充'ArrayList'后,不允许/可能进一步添加/删除对象。所以List不会动态变化。
在这样的条件下,多线程(同时)可以安全地使用这些数据结构(即ArraList
)吗?每个线程都只读取对象属性,但没有“set”操作可能。
所以,我的问题是我能依靠ArrayList
吗?如果没有,在这种情况下可以使用哪些其他较便宜的数据结构?
答案 0 :(得分:2)
如果在安全发布之后从未修改过线程,则可以在线程之间共享任何对象或数据结构。正如评论中所提到的,初始化ArrayList
的写入与其他线程获取引用的读取之间必须存在* before-before *关系。
E.g。如果您在启动其他线程之前或在将列表中的任务提交到ArrayList
之前完全设置ExecutorService
,那么您就是安全的。
如果线程已在运行,则必须使用其中一个线程安全机制将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"));
}
答案 1 :(得分:1)
是的,您应该能够将数组传递到每个线程中。只要在任何线程可能获取信息之前完成数组的写入,就不应该存在访问错误。