Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 向具有多个线程的列表中添加元素:如何使其线程安全?_Java_Concurrency_Java.util.concurrent - Fatal编程技术网

Java 向具有多个线程的列表中添加元素:如何使其线程安全?

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

我通过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))
         }
      }
公共类读取{
名单;
公共神话阅读(列表){
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.