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

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

问题描述

我几乎没有包含用户定义对象的 ArrayList(例如 List、List).对象本质上是不可变的,即不提供设置器 - 而且,由于问题的性质,没有人"永远不会尝试修改这些对象.一旦填充了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.

请记住,事后不再修改对象的前提必须始终成立.建议通过使用 Collections.unmodifiableList(...) 并且在发布之前忘记原始列表引用:

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天全站免登陆