我的java线程代码没有做我想要的

Ans*_*hul 0 java multithreading

为什么以下代码只输出3 Thread-0时输出6行Thread-1

public class NameList{

    private List names = new ArrayList();
    public synchronized void addName(String name){
        names.add(name);
    }

    public synchronized void print(){
        for (int i = 0; i < names.size(); i++) {
            System.out.print(names.get(i)+" ");
            System.out.println(Thread.currentThread().getName());
        }
    }

    public static void main(String args[]){

        final NameList nl = new NameList();
        for (int i = 0; i <2; i++) {

            new Thread(){
                public void run(){
                    nl.addName("A");
                    nl.addName("B");
                    nl.addName("C");
                    nl.print();
                }
            }.start();

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

A Thread-1
B Thread-1
C Thread-1
A Thread-0
B Thread-0
C Thread-0
A Thread-0
B Thread-0
C Thread-0
Run Code Online (Sandbox Code Playgroud)

Gra*_*ray 6

为什么Thread-0输出6次并且thread-1 3 ?????

因为每个线程都根据以下数量吐出消息NameList.names:

// the threads share the same `NameList`
final NameList nl = new NameList();
...
nl.addName("A");
...
for (int i = 0; i < names.size(); i++) {
Run Code Online (Sandbox Code Playgroud)

由于names在线程之间共享,因此您将修改两个线程中的列表.第一个线程添加3个名称,必须在第二个线程运行之前完成.然后第二个增加另一个3并吐出6.

如果你想要2个线程更新同一个列表,你应该通过使用并发集合或我在synchronized (names) {块内部进行添加来保护它.您的代码正在运行,因为它System.out.print()是一个同步类,因此它会导致在线程之间更新内存.如果您删除了这些print()调用,则每个线程names在运行时很可能会看到为空.它们也可能导致List损坏或其他不良.

至于为什么Thread-1吐出3 之前 Thread-0,线程是同时启动的,并且它是一个竞争条件,看看哪个先行.