为什么Unsynchronized ArrayList对象添加方法行为不正常

时间:2016-06-03 13:21:29

标签: java multithreading arraylist add

以下是示例代码

1)ArrayList是一个传递给ThreadPool的每个线程的单个对象。

2)在执行结束时,列表大小应该是50,如果你检查样本输出它可能不是50。有时它可能是41或47那样,为什么它表现得那样。

public class Test {

    ArrayList list=new ArrayList();
    public static void main(String[] args) {
        ExecutorService executorService3 = Executors.newScheduledThreadPool(10);
        Test test=new Test();
        for(int i=0;i<5;i++)
        {
            Mythread t1=new Mythread(test.list);

            executorService3.execute(t1);
        }

        executorService3.shutdown();

        while(executorService3.isShutdown())
        {
            //---This is not giveging proper output as expected is 50.--
            System.out.println("List size="+test.list.size());
            break;
        }
    }
}


class Mythread implements Runnable {

    List list=null;
    Mythread(List list) {
        this.list=list;
    }

    @Override
    public void run() {
        for(int i=0;i<10;i++) {
            this.list.add(i);   
        }
    }
}

3 个答案:

答案 0 :(得分:2)

您的代码不等待线程完成执行。当您的代码调用以下行

System.out.println("List size="+test.list.size());

不保证他们已经完成,因此无法保证该列表包含预期的50个项目。使用awaitTermination方法(https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination(long,%20java.util.concurrent.TimeUnit)),例如:

executorService3.shutdown();
executorService3.awaitTermination(1, TimeUnit.SECONDS);
System.out.println("List size="+test.list.size());

(为简洁省略了异常处理)

答案 1 :(得分:2)

正如Javadoc for ArrayList中所述:

  

请注意,此实施未同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步。

所以&#34;不正常行为&#34;因为您没有按照文档中的说明使用它。

正如Javadoc中所建议的那样,您可以将list包装在同步列表中:

List<Integer> list = Collections.synchronizedList(new ArrayList<>());

答案 2 :(得分:0)

这是一个并发问题。 我看到它的方式,你有: 5个线程将​​在同一个对象上执行run方法。多个线程可以在数组列表中的相同位置插入变量,因为它未同步。 你能打印清单的内容吗?