两个线程之间的同步Arraylist不会返回相同的值

时间:2019-01-18 20:06:25

标签: 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<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();
    }
}

输出应为: 2000000

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

我不知道问题出在哪里,对此代码进行了几次修改,但都没有解决问题。 (用Vector替换/在构造函数中添加了同步/在volatile中添加了

为什么此代码无法正常工作?

修改

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

2 个答案:

答案 0 :(得分:3)

  

输出应为:2000000

不,出于三个原因:

  1. 您要打印两件事,所以输出不会是一个数字。
  2. 当每个线程恰好添加了1000000个东西时,它会打印大小;您不知道其他线程在这一点上做了多少。
  3. 您没有以同步方式访问尺寸,因此您可能会获得最新的值。

答案 1 :(得分:2)

你正在得到

end: 1065878
end: 2000000

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

由于同步方法,第二行始终为2M(如您所预期)。

  

我猜第一个线程应该以我想要的确切数目执行,不多也不少。

事情并行发生。线程正在运行。每个人都试图调用updateList:一个人进入,其他人等待。没有人优先考虑下一个人,因此该方法的控制权以相当随机的方式传递给所有工人。

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

为了更好地理解它,请添加打印声明

private void updateList(int i) {
    synchronized (myList) {
        myList.add(i);
        System.out.println(Thread.currentThread().getName() + " added " + i);
    }
}

并减少要添加到任务的元素数量,例如10

pool-1-thread-1 added 0
pool-1-thread-1 added 1
pool-1-thread-1 added 2
pool-1-thread-1 added 3
pool-1-thread-2 added 0
pool-1-thread-2 added 1
pool-1-thread-2 added 2
pool-1-thread-2 added 3
pool-1-thread-1 added 4
pool-1-thread-1 added 5
pool-1-thread-1 added 6
pool-1-thread-1 added 7
pool-1-thread-1 added 8
pool-1-thread-1 added 9
end: 14
pool-1-thread-2 added 4
pool-1-thread-2 added 5
pool-1-thread-2 added 6
pool-1-thread-2 added 7
pool-1-thread-2 added 8
pool-1-thread-2 added 9
end: 20