ArrayList可以在多线程环境中用于只读目的吗? [英] Can ArrayList be used for readonly purpose in multithreaded environment?

查看:514
本文介绍了ArrayList可以在多线程环境中用于只读目的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只有几个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 finalvolatile字段中,也是最简单的形式.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆