ArrayList可以在多线程环境中用于只读目的吗? [英] Can ArrayList be used for readonly purpose in multithreaded environment?
问题描述
我只有几个ArrayList<T>
包含用户定义的对象(例如List<Student>, List<Teachers>
).这些对象本质上是不可变的,即不提供设置器-而且,由于问题的性质,没人"会尝试修改这些对象.一旦填充了"ArrayList",就不允许/不可能再添加/删除对象.因此List不会动态更改.
I have few ArrayList<T>
containing user defined objects (e.g. List<Student>, List<Teachers>
). The objects are immutable in nature, i.e. no setters are provided - and also, due to the nature of the problem, "no one" will ever attempt to modify these objects. Once the 'ArrayList' is populated, no further addition/removal of objects is allowed/possible. So List will not dynamically change.
在这种给定条件下,多个线程可以安全地同时使用此数据结构(即ArraList
)吗?每个线程将只读取对象属性,但是不可能进行设置"操作.
With such given condition, can this data structures (i.e. ArraList
) be safely used by multiple threads (simultaneously)? Each of the thread will just read the object-properties, but there is no "set" operation possible.
所以,我的问题是我可以依靠ArrayList
吗?如果不能,那么在这种情况下还可以使用其他更便宜的数据结构吗?
So, my question is can I rely on ArrayList
? If not, what other less expensive data structures can be used in such scenario?
推荐答案
如果在安全发布之后从未修改过任何对象或数据结构,则可以在线程之间共享任何对象或数据结构.如评论中所述,在初始化ArrayList
的写入与其他线程获取引用的读取之间,必须存在事前发生"关系.
You can share any objects or data structures between threads if they are never modified after a safe publication. As mentioned in the comments, there must be a * happen-before* relationship between the writes that initialize the ArrayList
and the read by which the other threads acquire the reference.
例如如果您在启动其他线程之前或在将列表中的工作提交给ExecutorService
之前完全设置了ArrayList
,您将很安全.
E.g. if you setup the ArrayList
completely before starting the other threads or before submitting the tasks working on the list to an ExecutorService
you are safe.
如果线程已经在运行,则必须使用一种线程安全机制将ArrayList
引用移交给其他线程,例如将其放在BlockingQueue
上.
If the threads are already running you have to use one of the thread safe mechanisms to hand-over the ArrayList
reference to the other threads, e.g. by putting it on a BlockingQueue
.
即使将引用存储到static final
或volatile
字段中,也是最简单的形式.
Even simplest forms like storing the reference into a static final
or volatile
field will work.
请记住,您以后永远不要修改对象的前提必须始终成立.建议通过使用
Keep in mind that your precondition of never modifying the object afterwards must always hold. It’s recommended to enforce that constraint by wrapping the list using Collections.unmodifiableList(…)
and forget about the original list reference before publishing:
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"));
}
这篇关于ArrayList可以在多线程环境中用于只读目的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!