java - 在两个线程上同步 ArrayList

标签 java multithreading arraylist

我很难理解如何在两个线程上同步 ArrayList。基本上,我希望一个线程将对象附加到列表中,而另一个线程同时从该列表中读取。

这是部署线程的类:

public class Main {
    public static ArrayList<Good> goodList = new ArrayList();
    public static void main(String[] args) {
        Thread thread1 = new Thread(new GoodCreator());
        Thread thread2 = new Thread(new WeightCounter());
        thread1.start();
        thread2.start();
    }
}

然后是两个Runnable类:

这个从文本文件中读取两个值的行并附加新对象。

public class GoodCreator implements Runnable{
    private ArrayList<Good> goodList = Main.goodList;
    private static Scanner scan;
    @Override
    public void run() {
        System.out.println("Thread 1 started");
        int objCount = 0;
        try {
            scan = new Scanner(new File(System.getProperty("user.home") + "//Goods.txt"));
        } catch (FileNotFoundException e) {
            System.out.println("File not found!");
            e.printStackTrace();
        }
        while(scan.hasNextLine()){
            String line = scan.nextLine();
            String[] words = line.split("\\s+");
            synchronized(goodList){
                goodList.add(new Good(Integer.parseInt(words[0]), Integer.parseInt(words[1])));
                objCount++;
            }
            if(objCount % 200 == 0) System.out.println("created " + objCount + " objects");
        }
    }

}

这遍历数组列表,应该对其中一个字段求​​和。

public class WeightCounter implements Runnable{
    private ArrayList<Good> goodList = Main.goodList;
    @Override
    public void run() {
        System.out.println("Thread 2 started");
        int weightSum = 0;
        synchronized(goodList){
            for(Good g : goodList){
                weightSum += g.getWeight();
            }
        }
        System.out.println(weightSum);

    }

}

无论输入如何,weightSum 永远不会递增并保持为 0

Thread 1 started
Thread 2 started
0

非常感谢任何帮助

最佳答案

您正在运行两个独立运行的线程。这些线程可以按任何顺序运行,如果一个线程停止,例如从文件中读取,另一个线程不认为它必须等待它。

简而言之,您的第二个线程在第一个线程向列表添加任何内容之前完成。

没有很好的解决办法,因为这不是您为什么要使用多线程的一个很好的例子,但是要获得结果,您可以这样做。

public class WeightCounter implements Runnable{
    private ArrayList<Good> goodList = Main.goodList;
    @Override
    public void run() {
        System.out.println("Thread 2 started");
        for(int i = 0; i < 10; i++) {
           try {
               Thread.sleep(100);
           } catch (InterruptedException ie) {
               throw AssertionError(ie);
           }
           int weightSum = 0;
           synchronized(goodList){
               for (Good g : goodList)
                    weightSum += g.getWeight();
           }
           System.out.println(weightSum);
        }
    }
}

这将打印总和 10 次,间隔 0.1 秒。根据您的文件加载所需的时间,您将能够看到到目前为止已加载的内容的总和。

关于java - 在两个线程上同步 ArrayList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36778020/

相关文章:

javascript - 您如何使用 Selenium WebDriver 和 NodeJS 测试 JavaScript 错误?

java - android:带有自定义适配器的AutoCompleteTextView

java - 如何制作java控制台菜单并使用这些选项调用项目中的不同java文件?

Java lambda 表达式 : Copy nodes from list to a new list

C++ 杀死一个 std::thread

c++ - 多生产者单消费者问题的信号量

ios - 调试核心数据 __NSCFSet addObject nil 异常

java - 如何对排名选择应用适当的成本

java - 字符串列表中单词的频率

java - 在不丢失第一个排序顺序的情况下进行子排序?