【发布时间】:2013-05-13 19:14:55
【问题描述】:
我有一个 Java 类,其中包含一个 ArrayList 的事务信息对象,这些对象经常被不同的线程查询和修改。在基本层面上,类的结构看起来像这样(目前不存在同步):
class Statistics
{
private List<TranInfo> tranInfoList = new ArrayList<TranInfo>();
// This method runs frequently - every time a transaction comes in.
void add(TranInfo tranInfo)
{
tranInfoList.add(tranInfo);
}
// This method acts like a cleaner and runs occasionally.
void removeBasedOnSomeCondition()
{
// Some code to determine which items to remove
tranInfoList.removeAll(listOfUnwantedTranInfos);
}
// Methods to query stats on the tran info.
// These methods are called frequently.
Stats getStatsBasedOnSomeCondition()
{
// Iterate over the list of tran info
// objects and return some stats
}
Stats getStatsBasedOnSomeOtherCondition()
{
// Iterate over the list of tran info
// objects and return some stats
}
}
我需要确保列表上的读/写操作正确同步,但是,性能非常重要,所以我不想最终锁定每个方法调用(尤其是并发读操作)。我查看了以下解决方案:
CopyOnWriteArrayList
我查看了使用 CopyOnWriteArrayList 来防止在迭代列表时修改列表时引发 ConcurrentModificationExceptions;这里的问题是每次修改列表时都需要复制...考虑到列表的修改频率和列表的潜在大小,这似乎太昂贵了。
读写锁
ReadWriteLock 可用于同步读/写操作,同时允许发生并发读操作。虽然这种方法可行,但最终会导致类中出现大量同步代码(但这并不是世界末日)。
有没有其他聪明的方法来实现这种同步而不会造成很大的性能损失,或者上述方法之一是推荐的方法吗?对此的任何建议将不胜感激。
【问题讨论】:
-
列表的修改频率如何?有多大?
-
ReadWriteLock 是 IMO 的正确解决方案。如果混合的问题让您感到困扰,请插入一个代理级别。
-
你知道这是个问题吗,因为我不认为你经常调用这些方法会导致问题。即是 1K/s、10K/s、100K/s 还是 1M/s?
-
如果您不想锁定每个方法调用,并且不想在每次写入时复制整个列表,则需要放弃对
List的随机排序访问。也许是ConcurrentLinkedQueue? -
看来你已经超出了ArrayList的设计意图。也许您应该考虑另一个更专业的容器。这听起来像是并发队列或同步列表的工作。你看过那些吗?
标签: java concurrency arraylist