我很困惑 - 这段代码总是有效吗?

时间:2010-04-30 09:15:44

标签: java list multithreading

我写了这段代码

public class Test{
public static void main(String[] args) {

    List<Integer> list = new ArrayList<Integer>();

    for(int i = 1;i<= 4;i++){
        new Thread(new TestTask(i, list)).start();
    }

    while(list.size() != 4){
        // this while loop required so that all threads complete their work
    }

    System.out.println("List "+list);
}

}

class TestTask implements Runnable{

private int sequence;
private List<Integer> list;

public TestTask(int sequence, List<Integer> list) {
    this.sequence = sequence;
    this.list = list;
}

@Override
public void run() {
    list.add(sequence);
}
}

此代码在我的机器上工作并打印列表的所有四个元素。

我的问题是,此代码始终有效。我认为当两个/或多个线程在同一点向此列表添加元素时,此代码中可能存在问题。在这种情况下,while循环将永远不会结束,代码将失败。

有人能建议更好的方法吗?我不是很擅长多线程,也不知道我可以使用哪个并发集合?

谢谢,Shekhar

5 个答案:

答案 0 :(得分:5)

使用它来获得真正的线程安全列表: List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());

根据您的使用情况,CopyOnWriteArrayList对您来说也很有趣。确切地说,当遍历操作大大超过该列表中的突变时。

答案 1 :(得分:2)

Afair,列表在Java中不是线程安全的,因此您可能会遇到从崩溃到崩溃的任何事情。使用对列表的同步访问以获得明确定义的行为:

@Override
public void run() {
    synchronized(list) {
        list.add(sequence);
    }
}

这样,只能对一个线程一次访问列表。

此外,我还会使用Thread.join()等待线程完成(您必须将它们保存在单独的列表中才能完成...)

答案 2 :(得分:1)

不,没有保证。最简单的解决方案是每个线程join

答案 3 :(得分:1)

我认为你需要做两件事。首先,您需要加入线程。因为atm,即使线程没有完成,其他循环有时也会运行。

你必须这样做:

Threads threads[4] = new Thread[4];

for(int i = 1;i<= 4;i++){
    threads[i] = new Thread(new TestTask(i, list));
    threads[i].start();
}

// to wait that all threads finish..
for(int i = 1;i<= 4;i++){
    threads[i].join();
 }


 while(list.size() != 4){
     // this while loop required so that all threads complete their work
 }

您可以将ArrayList线程安全地打包到:

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

答案 4 :(得分:0)

wait()notify()上阅读,而不是忙着等待while循环。