Java 为什么synchronizedList没有';你不能按预期工作吗?

Java 为什么synchronizedList没有';你不能按预期工作吗?,java,arraylist,Java,Arraylist,我已经编写了下面的程序,将创建三个线程并启动它们。每个线程的任务是迭代字符串列表。此列表是一个同步列表。当我运行程序时,我仍然看到线程输出没有同步。i、 例如,在第一个线程遍历列表中的所有内容之前,第二个线程中断,第三个线程中断,以此类推 import java.util.*; public class Program implements Runnable{ List<String> stars = Collections.synchronizedList(new Arra

我已经编写了下面的程序,将创建三个线程并启动它们。每个线程的任务是迭代字符串列表。此列表是一个同步列表。当我运行程序时,我仍然看到线程输出没有同步。i、 例如,在第一个线程遍历列表中的所有内容之前,第二个线程中断,第三个线程中断,以此类推

import java.util.*;
public class Program implements Runnable{
    List<String> stars = Collections.synchronizedList(new ArrayList<String>());
    public static void main(String[] ars){
        System.out.println(Thread.currentThread().getName());   
        Program p = new Program();
        p.init();
    }
    public void init(){
        stars.add("Tom Hanks");
        stars.add("Bruce Lee");
        stars.add("Matthew");
        stars.add("fasbender");
        stars.add("pitt");
        Thread one = new Thread(this);
        one.setName("First");
        Thread two = new Thread(this);
        two.setName("Two");
        Thread three = new Thread(this);
        three.setName("Three");
        one.start();
        two.start();
        three.start();

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

列表
完全同步,但是从线程的角度来看,访问顺序是不可预测的,并且完全取决于线程调度程序。因此,如果您想要一致的行为,则必须对列表本身进行
同步
(将其包含在
同步
块中,并将列表作为参数。
查看以了解更多详细信息。

另外,请查看答案以获得更多解释。

同步列表上的迭代不是原子的。客户端必须提供锁定

如果您查看
Collections.synchronizedList
的源文档,它将返回的列表用作锁(互斥)。因此,客户端代码可以通过使用返回的列表应用同步块来使迭代原子化

来自SynchronizedCollection的Java代码

SynchronizedCollection(Collection<E> c) {
    this.c = Objects.requireNonNull(c);
    mutex = this;
}
在本例中,即使在客户端代码上进行了同步之后,线程操作的顺序仍然是不确定的,并且取决于线程调度程序。可以在线程2之前调用线程3

public void run(){

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

在我看来是正确的。为什么你希望第一个线程在第二个线程开始之前完成?检查答案,也许它会为你清除它。
static class SynchronizedList<E>
        extends SynchronizedCollection<E>
        implements List<E> {
...
...
    public void add(int index, E element) {
        synchronized (mutex) {list.add(index, element);}
    }
}
public void run(){

        synchronized (stars) {
            for(int i=0;i<stars.size();i++){
                System.out.println(stars.get(i)+" "+Thread.currentThread().getName());
            }
        }
    } 
main
Tom Hanks First
Bruce Lee First
Matthew First
fasbender First
pitt First
Tom Hanks Three
Bruce Lee Three
Matthew Three
fasbender Three
pitt Three
Tom Hanks Two
Bruce Lee Two
Matthew Two
fasbender Two
pitt Two