当我使用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的源代码,但没有找到奇怪结果的答案。
请帮我解决一下,谢谢!
答案 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上的同步不是必需的。