多个线程在Java中修改集合?

5
我正在处理的项目需要向数据库发出大量查询。原则上,我使用两种类型的查询:
1. 读取Excel文件,检查一些参数,并查询数据库中的命中。这些命中随后将被注册为一系列自定义类。任何命中都可能(并且很可能)会多次发生,因此代码的这部分会检查并更新自定义列表实现中的出现次数,该列表扩展了ArrayList。
2. 对于找到的每个命中,执行详细查询并解析输出,以便在步骤1中创建的类获得详细信息。
我想使用多个线程来优化时间效率。然而,我无法想出一个解决存储这些项的集合出现的问题的好方法。稍微解释一下;在整个执行过程中,对象应该由(I)和(II)修改。
我故意没有复制/粘贴任何代码,因为它们必须是大块代码才有意义。希望以上描述有些道理。
谢谢,
2个回答

8
在Java 5及以上版本中,您可以使用CopyOnWriteArrayList或对列表进行同步封装。在早期的Java版本中,只有后者可用。如果您一定要坚持使用自定义的ArrayList实现,则也只能选择后者。
如果容器被频繁读取而不是写入(更改),则CopyOnWriteArrayList是可行的,这似乎根据您的解释是正确的。它的原子addIfAbsent()方法甚至可以帮助简化您的代码。 [更新] 经过再次考虑,针对您描述的用例,显然使用map更加合适。因此,如果从列表更改为例如map是一个选项,您应该考虑ConcurrentHashMap[/更新] 更改容器内的对象不会影响容器本身,但是您需要确保对象本身是线程安全的。

CopyOnWriteArrayList是一个非常缓慢(且占用内存大)的数据结构 - 它也不扩展ArrayList,所以可以使用更有效的类,例如ConcurrentLinkedQueue。 - Gandalf
此外,只要您坚持使用生产者/消费者模型(即线程从队列中删除对象,对其进行编辑,然后将其放回(或放入不同的队列)),那么对象本身就不需要是线程安全的。 - Gandalf
@Gandalf,CopyOnWriteArrayList 在写入时速度较慢。对我来说,上面的帖子描述的与生产者-消费者模型非常不同,因此队列不是一个选项。 - Péter Török
感谢Peter和Gandalf,很抱歉回复晚了。我一直在为项目开发其他功能而忙碌。由于多线程被降低优先级以实现其他功能,我还没有尝试过这些功能。如果有机会尝试,我会再次回复。再次感谢。 - posdef

3

只需使用新的java.util.concurrent包。

ConcurrentLinkedQueueConcurrentHashMap这样的类已经可以供您使用,并且都是线程安全的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接