返回Java数组与集合

返回Java数组与集合,java,multithreading,arrays,memory,collections,Java,Multithreading,Arrays,Memory,Collections,我正在考虑java应用程序中内存分配和多线程的一些设计,这就是我想知道的: 我有一个类,它有一个同步的集合,比如一个列表,它每秒更新几次,但是所有的更新都发生在这个类和它自己的线程中,而不是来自其他线程。但是,我还有许多其他线程调用getCollection()方法,并使用foreach以只读方式迭代其内容。这是我不知道的: 如果另一个线程正在迭代同步收集,那么执行更新的单个线程是否必须等到没有其他线程在迭代的时间点 我的第二个问题是,返回集合的数组副本而不是集合本身似乎是有意义的。要返回数组,

我正在考虑java应用程序中内存分配和多线程的一些设计,这就是我想知道的:

我有一个类,它有一个同步的集合,比如一个列表,它每秒更新几次,但是所有的更新都发生在这个类和它自己的线程中,而不是来自其他线程。但是,我还有许多其他线程调用getCollection()方法,并使用foreach以只读方式迭代其内容。这是我不知道的:

如果另一个线程正在迭代同步收集,那么执行更新的单个线程是否必须等到没有其他线程在迭代的时间点

我的第二个问题是,返回集合的数组副本而不是集合本身似乎是有意义的。要返回数组,但从内存的角度考虑,不必每次都分配一个与集合内容大小相同的新数组,如果一个集合每秒被调用数百次里面有几千个物体,我不知道有没有意义

此外,如果我从未返回集合本身,则不再需要同步列表

如有任何意见,我们将不胜感激。谢谢邓肯

如果另一个线程正在迭代 同步采集将在单个 执行更新的线程具有 等到某个时间点没有 其他线程正在迭代

如果你说的是同步(不是并发)收集,那么是的。 至于第二个问题,它是
看起来像是
java.util.concurrent.CopyOnWriteArrayList的真实用例

我建议您使用CopyOnWriteArrayList。这是线程安全的,可以被任意数量的线程高效地读取和访问。如果你有少量的更新,这应该是好的

不过,请回答您的问题。如果在对同步集合进行修改时对其进行迭代,您将得到ConcurrentModificationException(COWAL没有得到此消息),您的更新不会被此阻止,只有您的读者会遇到问题

不是每次调用getCollection时都创建一个副本,而是每次修改集合时都创建一个副本(频率要低得多),这就是COWAL为您所做的


如果您按需返回一个副本,您仍然需要同步该集合。

处理此问题的最简单方法可能是保留两个集合:一个由类本身更新,另一个在调用
getCollection()
时返回的易失性字段中的只读副本

后者需要由在批准时更新主集合的进程重新创建。这允许您以原子方式更新集合:一次性更改多个元素,同时隐藏中间状态


如果您的更新不频繁,并且每次更新都会使集合处于一致状态,那么请使用已建议的CopyOnWriteArrayList。

似乎经常更新集合,并且频繁调用#getCollection()。您可以使用CopyOnWriteArrayList,但每次修改数组时都会创建一个副本。因此,您需要了解这将如何影响性能

另一个选项是每次调用#getCollection时,都让类中的线程进行复制。这将涉及#getCollection等待内部类线程完成

如果您只希望#getCollection返回最近的副本而不是最新的副本,那么您可以让内部线程定期创建在#getCollection中返回的集合的副本。副本需要是易失性的或原子引用