java - ArrayList 可以在多线程环境中用于只读目的吗?

标签 java multithreading arraylist

我很少ArrayList<T>包含用户定义的对象(例如 List<Student>, List<Teachers> )。这些对象本质上是不可变的,即没有提供 setter ——而且,由于问题的性质,“没有人”会尝试修改这些对象。一旦填充了“ArrayList”,就不允许/不可能进一步添加/删除对象。所以List不会动态变化。

在这样给定的条件下,这个数据结构(即 ArraList )能否被多线程(同时)安全使用?每个线程只会读取对象属性,但不可能进行“设置”操作。

所以,我的问题是我可以依赖 ArrayList ?如果不是,在这种情况下可以使用哪些其他更便宜的数据结构?

最佳答案

您可以在线程之间共享任何对象或数据结构,前提是它们在安全发布 后从未被修改过。如评论中所述,初始化 ArrayList 的写入与其他线程获取引用的读取之间必须存在 * happen-before* 关系。

例如如果您在启动其他线程之前或在将处理列表的任务提交给 ExecutorService 之前完全设置了 ArrayList,那么您是安全的。

如果线程已经在运行,您必须使用一种线程安全机制将 ArrayList 引用移交给其他线程,例如通过将其放入 BlockingQueue

即使是最简单的形式,如将引用存储到 static finalvolatile 字段中也可以。

请记住,事后永不修改对象的先决条件必须始终成立。建议通过使用 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/

相关文章:

java - spring-data-jpa 中的交叉连接

java - 多线程Java程序中的连接池

java - 我的 ListView 重叠在我的编辑文本上

java - Java Swing 模型/MVC 的目的

java - 即使线程尚未运行完毕,如何终止该线程?

c# - 如何从文本文件中读取并存储到 C# 中的数组列表?

Java:优化/提高 DFS 中的运行速度

c# - 如何声明一个字节数组列表

java - 如何从数组中删除一个元素?

c++ - 管道+选择: select never woken up