我通过ExecutorService使用多个线程将对象添加到具有多个for循环的列表中。由于普通的ArrayList不是线程安全的,我使用的是CopyOnWriteList。但是,在下面的代码示例中添加元素并没有给我一个(n1 + n2)元素的列表,所以不知何故存在并发问题。
我思考的错误在哪里? CopyOnWriteList是线程安全列表的正确选择吗?
public class myThread{
List<SomeObject> list;
public myThread(List<someObject> list){
this.list = list;
}
public void run(){
SomeObject instance = new SomeObject();
list.add(instance);
}
}
public static void main(String[] args) {
CopyOnWriteArrayList<someObject> syncList = new CopyOnWriteList<someObject>();
ExecutorService executor = Executors.newFixedThreadPool(4);
for(int i=0; i< n1; i++){
executor.submit(new myThread(syncList))
}
for(int i=0; i< n2; i++){
executor.submit(new myThread(syncList))
}
}
答案 0 :(得分:3)
CopyOnWriteArrayList是一个线程安全列表。
public class myThread implements Runnable {
List<String> list;
public myThread(List<String> list){
this.list = list;
}
public void run(){
String instance = "";
list.add(instance);
}
public static void main(String[] args) throws Exception {
CopyOnWriteArrayList<String> syncList = new CopyOnWriteArrayList<String>();
ExecutorService executor = Executors.newFixedThreadPool(4);
for(int i=0; i< 10; i++){
executor.submit(new myThread(syncList));
}
for(int i=0; i< 20; i++){
executor.submit(new myThread(syncList));
}
executor.shutdown();
while (executor.awaitTermination(1, TimeUnit.DAYS)) {
break;
}
System.out.println(syncList.size());
}
}
你试试这个。您可以在完成所有线程之前致电。
答案 1 :(得分:0)
上面的代码不起作用,因为你从未将列表传递给线程(因为它不是extend Thread
而不是线程)。尝试
...new myThread(syncList)...
然后它会工作,但如果列表变得非常大,性能可能会很慢。在这种情况下,最好在列表上进行同步:
synchronized(list) { list.add(instance); }
synchronized
在这里运作良好。请注意,元素可能在列表中以奇数顺序出现。这是因为两个线程都在“相同”时间添加元素,因此您不会看到n1+n2
,而是n1
和n2
元素的混合。 n1
中所有元素的顺序都是相同的,但n2
之间的元素会混合在一起。
答案 2 :(得分:0)
我的想法出错在哪里?
您没有在线程中共享列表。你的代码甚至无法编译。要解决此问题,请将列表传递给myThread构造函数:
for(int i=0; i< n1; i++){
executor.submit(new myThread(syncList))
}
CopyOnWriteList是否是线程安全列表的正确选择?
当读取次数远大于写入次数时,最好使用 CopyOnWriteList
。您的情况似乎正好相反,因此最好使用java.util.Collections.synchronizedList()
。
注意:来自Java Concurency in Practice:
CopyOnWriteArrayList is a concurrent replacement for a synchronized
List that offers better concurrency in some common situations and
eliminates the need to lock or copy the collection during iteration.