使用CopyOnWriteArrayList时为什么结果很奇怪?

时间:2014-01-23 02:09:18

标签: java

当我使用MultiOreads与CopyOnWriteArrayList时,输出结果有时不是目标。 代码是:

public class CopyOnWriteArrayListTest {

    public static void main(String[] args) throws InterruptedException {
        while(true){

        CopyOnWriteArrayList<String> ll = new CopyOnWriteArrayList<String>(new String[10]);

        CountDownLatch latch = new CountDownLatch(2);
        ThreadDemo t1 = new ThreadDemo(0, ll, latch);
        ThreadDemo t2 = new ThreadDemo(1, ll, latch);

        t1.start();
        t2.start();

        latch.await();
        System.out.println(ll);
        }
    }
}

public class ThreadDemo extends Thread implements Runnable {
    private int code;
    private List<String> list;
    private CountDownLatch latch;
    public ThreadDemo(int i, List<String> l, CountDownLatch latch){
        code = i;
        list = l;
        this.latch = latch;
    }

    @Override
    public void run() {
        writeList(list);
    }

    private synchronized void writeList(List<String> l){
        l.add(code, String.valueOf(code));
        latch.countDown();
    }

}

输出为[0,1,null,null,null,null,null,null,null,null,null,null]或 [0,null,1,null,null,null,null,null,null,null,null,null]。 它应始终为[0,1,null,null,null,null,null,null,null,null,null,null]。

我观看了CopyOnWriteArrayList的源代码,但没有找到奇怪结果的答案。

请帮我解决一下,谢谢!

1 个答案:

答案 0 :(得分:1)

当你添加一个元素时,你正在有效地移动列表,而不是替换那个索引,所以当在0处加上时,位置1的那个变成位置2.所以每当插入到位置1时,第二个元素将出现0. ie:

CopyOnWriteArrayList<String> ll = new CopyOnWriteArrayList<String>(new String[10]);
ll.add(1, "1");
ll.add(0, "0");
System.out.println(ll); 

>>> [0, null, 1, null, null, null, null, null, null, null, null, null]

这不会一直发生,因为通常因为你启动首先插入0的线程。如果你翻转产生线程的顺序,你几乎会不断地看到它。

我认为你要找的是“设定”方法

list.set(code, String.valueOf(code));

更改为它将提供您期望的输出。另外值得一提的是COWList是线程安全的,因此writeList上的同步不是必需的。