java我需要一个并发集合来通过多个线程向列表中添加元素吗?
static final Collection<String> FILES = new ArrayList<String>(1);
for (final String s : list) {
new Thread(new Runnable() {
public void run() {
List<String> file2List = getFileAsList(s);
FILES.addAll(file2List);
}
}).start();
}
这个集合非常大,但代码工作得非常完美。我想我会得到一个并发修改异常,因为文件列表必须扩展其大小,但它从未发生过
这个代码是100%线程安全的吗
加载代码需要12秒钟,几个线程同时添加元素
我试图先创建线程,然后运行它们,但得到了相同的结果(时间和正确性)
# 1 楼答案
不,代码不是线程安全的。它可能抛出
ConcurrentModificationException
,也可能不抛出,但最终可能会丢失元素或添加两次元素。将列表更改为假设最耗时的部分是
getFilesAsList
方法(并且而不是将结果元素添加到FILES
列表中),这可能已经是一个解决方案顺便说一句:当
getFileAsList
访问硬盘时,你应该进行详细的性能测试。多线程硬盘驱动器访问可能比单线程硬盘驱动器访问慢,因为硬盘驱动器头可能必须在驱动器周围跳跃,并且不能作为连续块读取数据编辑:回应评论:该节目“很可能”会不时制作
ArrayIndexOutOfBoundsExceptions
:但当然,没有严格的保证它会。如果它不为你创造这样一个例外,你应该考虑玩彩票,因为你一定非常幸运。p>
# 2 楼答案
是的,您需要一个并发列表来防止
ConcurrentModificationException
以下是在Java中初始化并发列表的一些方法:
# 3 楼答案
即使只添加元素,也根本不是线程安全。如果只增加
FILES
,那么如果集合不是线程安全的,也会出现一些多访问问题当集合超过它们的大小时,它必须被复制到新的空间,在那一刻,您可能会遇到并发访问的问题,因为在那一刻,一个线程将执行
copy
任务。。。另一种方法是尝试在同一时间向该集合添加元素,调整大小由内部arraylist实现完成,但它根本不是线程安全的检查该代码,并假设在收集容量已满时有多个线程执行该代码
当集合需要超出其容量并将现有元素复制到新的内部阵列时,您可能会遇到多访问的实际问题,此外,大小不是线程,因为它不是易失性的,它可以被某些线程缓存,并且可以有重写:)这就是为什么即使只对非同步集合使用添加操作,它也可能不是线程安全的答案
应考虑使用^ {CD3>}或^ {CD4>},其中Adx操作是线程安全的。