Java 向具有多个线程的列表中添加元素:如何使其线程安全?
我通过ExecutorService使用多个线程将对象添加到具有多个for循环的列表中。因为普通的ArrayList不是线程安全的,所以我使用的是CopyOnWriteList。但是,在下面的代码示例中添加元素并没有给出(n1+n2)元素的列表,因此存在并发问题 我的思维错误在哪里?CopyOnWriteList是线程安全列表的正确选择吗Java 向具有多个线程的列表中添加元素:如何使其线程安全?,java,concurrency,java.util.concurrent,Java,Concurrency,Java.util.concurrent,我通过ExecutorService使用多个线程将对象添加到具有多个for循环的列表中。因为普通的ArrayList不是线程安全的,所以我使用的是CopyOnWriteList。但是,在下面的代码示例中添加元素并没有给出(n1+n2)元素的列表,因此存在并发问题 我的思维错误在哪里?CopyOnWriteList是线程安全列表的正确选择吗 public class myThread{ List<SomeObject> list; pub
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))
}
}
公共类读取{
名单;
公共神话阅读(列表){
this.list=列表;
}
公开募捐{
SomeObject实例=新建SomeObject();
列表。添加(实例);
}
}
公共静态void main(字符串[]args){
CopyOnWriteArrayList syncList=新建CopyOnWriteList();
ExecutorService executor=Executors.newFixedThreadPool(4);
对于(int i=0;i
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());
}
}
公共类myThread实现可运行{
名单;
公共神话阅读(列表){
this.list=列表;
}
公开募捐{
字符串实例=”;
列表。添加(实例);
}
公共静态void main(字符串[]args)引发异常{
CopyOnWriteArrayList syncList=新建CopyOnWriteArrayList();
ExecutorService executor=Executors.newFixedThreadPool(4);
对于(int i=0;i<10;i++){
执行人提交(新的myThread(syncList));
}
对于(int i=0;i<20;i++){
执行人提交(新的myThread(syncList));
}
executor.shutdown();
而(执行人等待终止(1,时间单位:天)){
打破
}
System.out.println(syncList.size());
}
}
你试试这个。您可以在所有线程完成之前调用。上述代码不起作用,因为您从未将列表传递到线程中(该列表不是线程,因为它不扩展线程)。试一试 然后它就可以工作了,但是如果列表太大,性能可能会很慢。在这种情况下,最好在列表上同步:
synchronized(list) { list.add(instance); }
synchronized
在这里可以很好地工作。请注意,元素在列表中可能以奇数顺序出现。这是因为两个线程同时添加它们的元素,所以您不会看到n1+n2
,而是n1
和n2
元素的混合。来自n1
的所有元素的顺序将是相同的,但它们之间将混合来自n2
的元素。我的想法中的错误在哪里?
您没有在线程之间共享列表。你的代码甚至没有编译。要解决此问题,请将列表传递给myThread构造函数:
for(int i=0; i< n1; i++){
executor.submit(new myThread(syncList))
}
当读操作优于写操作时,CopyOnWriteList很好,因为每次写入(添加、设置等)时为了了解CopyOnWriteList的工作原理,我们制作了一个新的底层数组副本:上面的代码示例不起作用,因为您从未将
syncList
传递到myThread
。CopyOnWriteArrayList是线程安全的。您的代码甚至不会编译。
for(int i=0; i< n1; i++){
executor.submit(new myThread(syncList))
}
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.