Java 两个线程之间的Synchronized Arraylist不返回相同的值

Java 两个线程之间的Synchronized Arraylist不返回相同的值,java,multithreading,Java,Multithreading,我有以下代码: import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class MyThread implements Runnable{ private List<Integer> myList; public MyThread(List<

我有以下代码:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class MyThread implements Runnable{

    private List<Integer> myList;

    public MyThread(List<Integer> list){
            this.myList = list;
    }
    private void updateList(int i){
           synchronized (myList) {
               myList.add(i);
           }
    }
    @Override
    public void run() {
        for( int i = 0; i < 1000000;i++){
                updateList(i);
        }
        System.out.println("end: " + myList.size());
    }
}
public class MyExecutor {

    private List<Integer> taskList = new ArrayList<>();
    private void launch(){

        ExecutorService executorService= Executors.newFixedThreadPool(10000);
        executorService.execute(new MyThread(taskList));
        executorService.execute(new MyThread(taskList));
        executorService.shutdown();
    }
    public static void main(String[] args) {
        MyExecutor test = new MyExecutor();
        test.launch();
    }
}
产量应为:200万

我将得到不同的结果,这意味着这两个线程正在替换彼此的值

我不知道问题出在哪里,尝试了对代码的几次修改,但都没有解决问题。替换为矢量/在构造函数中添加同步/添加volatile

为什么这个代码不能正常工作

编辑

在这两个线程中,我都希望得到1000000

产量应为:200万

没有,原因有三:

您正在打印两个内容,因此输出不会是单个数字。
当每个线程碰巧添加了1000000个东西时,它会打印大小;您不知道另一个线程在这一点上完成了多少工作。 您没有以同步方式访问大小,因此可能会得到非最新值。 产量应为:200万

没有,原因有三:

您正在打印两个内容,因此输出不会是单个数字。
当每个线程碰巧添加了1000000个东西时,它会打印大小;您不知道另一个线程在这一点上完成了多少工作。 您没有以同步方式访问大小,因此可能会得到非最新值。 你越来越

end: 1065878
end: 2000000
第一行来自首先完成其任务的线程。它不应该正好是1M,因为有几个线程正在工作。可以合理地假设,当第一个线程完成添加1M时,另一个线程至少添加了一个

由于采用了同步方法,第二条线路始终如您所预期的2米


我想第一个线程应该按照我想要的确切数字执行,不多不少

事情同时发生。线程正在运行。每个人都试图调用updateList:一人输入,其他人等待。谁应该是下一个并没有优先权,所以对这种方法的控制是以一种相当随机的方式在所有工人中传递的

我打赌您仍然在考虑顺序执行:一个线程运行整个run方法,打印1M,另一个线程获取1M大小的列表并添加其部分

要更好地理解它,请添加打印语句

private void updateList(int i) {
    synchronized (myList) {
        myList.add(i);
        System.out.println(Thread.currentThread().getName() + " added " + i);
    }
}
并将一个任务要添加的元素数量减少到10个

你越来越

end: 1065878
end: 2000000
第一行来自首先完成其任务的线程。它不应该正好是1M,因为有几个线程正在工作。可以合理地假设,当第一个线程完成添加1M时,另一个线程至少添加了一个

由于采用了同步方法,第二条线路始终如您所预期的2米


我想第一个线程应该按照我想要的确切数字执行,不多不少

事情同时发生。线程正在运行。每个人都试图调用updateList:一人输入,其他人等待。谁应该是下一个并没有优先权,所以对这种方法的控制是以一种相当随机的方式在所有工人中传递的

我打赌您仍然在考虑顺序执行:一个线程运行整个run方法,打印1M,另一个线程获取1M大小的列表并添加其部分

要更好地理解它,请添加打印语句

private void updateList(int i) {
    synchronized (myList) {
        myList.add(i);
        System.out.println(Thread.currentThread().getName() + " added " + i);
    }
}
并将一个任务要添加的元素数量减少到10个


这就是你的意思吗?synchronized myList{System.out.printlnend:+myList.size;}@Vahidhashemi不同步访问大小只能在1之前给出结果“我错了吗?”对于第1点,请等待两者都完成。可以通过以下方式完成:''executorService.awaitTermination…',然后打印最终大小。当每个线程碰巧添加了1000000个东西时,它会打印大小;您不知道另一个线程在这一点上完成了多少工作。第二次打印应该是正确的。第二次打印是正确的,但我希望第一次打印是正确的。这就是你的意思吗?synchronized myList{System.out.printlnend:+myList.size;}@Vahidhashemi不同步访问大小只能在1之前给出结果“我错了吗?”对于第1点,请等待两者都完成。可以通过以下方式完成:''executorService.awaitTermination…',然后打印最终大小。当每个线程碰巧添加了1000000个东西时,它会打印大小;您不知道另一个线程在这一点上完成了多少工作。第二次打印应该是正确的。第二次打印是正确的,但我希望第一次打印是正确的。我想第一个线程应该按照我想要的确切数字执行,不多不少。确实如此!但其他线程也添加了元素。第一次打印可以提供1000000到20之间的任何内容
0第二次打印将始终精确到2000000。次要细节:实际上允许10000个线程。不过,只有两项工作是可以运行的。所以只有两个线程会被使用。我想第一个线程应该按照我想要的确切数字执行,不多不少。确实如此!但其他线程也添加了元素。第一次打印可以提供1000000到200000之间的任何内容。第二次打印将始终精确到2000000。次要细节:实际上允许10000个线程。不过,只有两项工作是可以运行的。所以只能使用两个。在两个线程完成后尝试打印大小。在两个线程上,我期望得到1。在两个线程完成后尝试打印大小。在两个线程上,我期望得到1