我的java线程代码没有';我不能做我想做的事

我的java线程代码没有';我不能做我想做的事,java,multithreading,Java,Multithreading,当Thread-1仅输出3行时,为什么以下代码有Thread-0输出6行 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

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

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();

        }
    }
}
为什么线程0输出6次,线程1输出3次

因为每个线程都是基于
名称列表的数量吐出消息。名称

// the threads share the same `NameList`
final NameList nl = new NameList();
...
nl.addName("A");
...
for (int i = 0; i < names.size(); i++) {
//线程共享相同的`名称列表`
最终名称列表nl=新名称列表();
...
nl.地址名称(“A”);
...
对于(int i=0;i
由于
名称
在两个线程之间共享,因此您正在修改两个线程中的列表。第一个线程添加3个名称,并且必须在第二个线程运行之前完成。然后第二个线程添加另外3个名称,并吐出6个名称

如果您想让两个线程更新同一个列表,您应该使用并发集合或my在
synchronized(names){
块中进行添加来保护它。您的代码之所以能够工作,是因为
System.out.print()
是一个同步类,因此它会导致线程之间的内存更新。如果删除
print()
调用,则每个线程在运行时很可能会将
名称
视为空的。它们还可能导致
列表
损坏或其他不良行为

至于为什么
Thread-1
Thread-0
之前吐出3,线程同时启动,看哪一个先开始是一种竞争条件

为什么线程0输出6次,线程1输出3次

因为每个线程都是基于
名称列表的数量吐出消息。名称

// the threads share the same `NameList`
final NameList nl = new NameList();
...
nl.addName("A");
...
for (int i = 0; i < names.size(); i++) {
//线程共享相同的`名称列表`
最终名称列表nl=新名称列表();
...
nl.地址名称(“A”);
...
对于(int i=0;i
由于
名称
在两个线程之间共享,因此您正在修改两个线程中的列表。第一个线程添加3个名称,并且必须在第二个线程运行之前完成。然后第二个线程添加另外3个名称,并吐出6个名称

如果您想让两个线程更新同一个列表,您应该使用并发集合或my在
synchronized(names){
块中进行添加来保护它。您的代码之所以能够工作,是因为
System.out.print()
是一个同步类,因此它会导致线程之间的内存更新。如果删除
print()
调用,则每个线程在运行时很可能会将
名称
视为空的。它们还可能导致
列表
损坏或其他不良行为


至于为什么
Thread-1
Thread-0
之前吐出3个线程,线程同时启动,看哪个线程先开始是一个竞争条件。

因为每个线程将3个名称添加到列表中,所以,在第二个线程运行后,您将添加6个名称,两个线程中的一个将打印所有名称。

因为每个线程向列表中添加了3个名称,所以在第二个线程运行后,您添加了6个名称,两个线程中的一个将打印所有名称