当前位置: 首页 > 知识库问答 >
问题:

尽管已同步,Vector仍会抛出ConcurrentModificationException

许阿苏
2023-03-14

我有一个由多个线程操作的ArrayList,由于ArrayList没有同步,所以无法工作。按照教授的指示,我把列表换成了向量。向量是同步的,但我抛出了与同步相关的异常。

为什么会发生这种情况,我如何避免代码中的并发异常?我不想只是玩玩,直到有东西起作用,我想做最好的事情。谢谢!

例外情况:

Exception in thread "Thread-3" java.util.ConcurrentModificationException
    at java.util.Vector$Itr.checkForComodification(Vector.java:1184)
    at java.util.Vector$Itr.next(Vector.java:1137)
    at BytePe4D$ReadInts.run(BytePe4D.java:64)

代码:

import java.io.*;
import java.util.Vector;

public class BytePe4D {
    private Vector<Integer> numbers;

    public static void main(String[] args) {
        new BytePe4D();
    }

    public BytePe4D() {
        // Create ArrayList and reset sum
        numbers = new Vector<Integer>();

        // Call addInts 8 times, with filenames integer1.dat through integer8.dat
        for (int i = 1; i <= 8; i++) {
            File file = new File("PE Data/integer" + i + ".dat");
            ReadInts thread = new ReadInts(file);
            thread.start();
        }
    }

    /** Represents a Thread instance */
    class ReadInts extends Thread {
        File file;

        public ReadInts(File _file) {
            file = _file;
        }

        @Override
        public void run() {
            int count = 0;  // track number of records read
            int sum = 0;

            try {
                // Open stream to binary data file integer1.dat
                FileInputStream in = new FileInputStream(file);
                // Buffer the stream
                BufferedInputStream bin = new BufferedInputStream(in);
                // Access the primitive data
                DataInputStream din = new DataInputStream(bin);

                try {
                    // Read file until end reached
                    while (true) {
                        numbers.add(din.readInt());
                        count++;
                    }
                } catch (EOFException eof) {
                    // System.out.println("End of file reached.");
                } finally {
                    // Close streams
                    din.close();
                }
            } catch (FileNotFoundException fnf) {
                System.out.println("File does not exist: " + file.getName());
                return;
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }

            // Calculate sum of numbers read
            for (int num : numbers) {
                sum += num;
            }

            // Write info
            System.out.println(
                String.format("%s%s%-5s%s%-8d%-5s%s%-12d%-5s%s%d",
                "Filename = ", file.getName(), "",
                "Count = ", count, "",
                "Sum = ", sum, "",
                "In List = ", numbers.size()));
        }
    }

}

共有2个答案

顾骏祥
2023-03-14

来自文档:

如果在创建迭代器后的任何时候,以迭代器自己的remove或add方法之外的任何方式对向量进行结构修改,迭代器将抛出ConcurrentModificationException。

下面的代码在幕后创建了一个迭代器:

for (int num : numbers) {
    sum += num;
}

因此,当一个线程(通过添加元素)修改向量,而另一个向量正在迭代它时,您将看到一个ConcurrentModificationException

解决这个问题有不同的方法,一种方法是从一个文件读入另一个向量,读取完成后,将另一个向量分配给数字(因为分配是一个原子操作)。请记住,为了使更改对其他线程可见,您需要将numbers声明为volatile

颛孙品
2023-03-14

你的代码似乎错了。

如果每个线程都要计算单个文件中记录的总和,我不明白为什么需要共享向量。另一方面,如果要计算所有文件的记录之和,应该在每个线程完成后进行。

根据需要,您可以1)为每个线程创建一个向量并计算每个文件的总和,或者2)在主线程中,等待所有线程完成,然后计算所有文件的总和。

 类似资料:
  • 我试图读取一个CSV文件,然后根据该CSV文件创建一个新的对象。我可以用SuperCSV库成功地做到这一点,但是如果发生错误(例如特定的单元格为null),它会抛出一个错误(如预期的那样)。我试图在ArrayList中收集所有错误,但现在第一个异常时一切都会停止。如何使SuperCSV CsvBeanReader继续到下一行,即使处理器出现错误?我在try/catch块中有循环条件。代码如下:

  • 我有一些(C 14)代码如下所示: 有时会抛出一个异常,这很好,因为如果是这样,我不希望垃圾映射中的值。 但是一开始我在循环中写了这个,这不起作用: 更准确地说,即使抛出异常,也会创建(并分配一个空集)。 这不是我所期望的:我希望它们以同样的方式运行。 这里有没有我误解的C原则?

  • 问题内容: 在我用Swift编写的SpriteKit iOS游戏中,播放非常短的声音(约0.5秒)会产生打ic(如滞后)。在其他问题中,我读到我应该发出声音,就像以前那样。 我什至使用变量()在播放之前检查声音是否准备就绪。每当播放完()时,我也会重新准备声音。以下是代码的相关部分: 我不知道我在哪里犯了错误。我感觉我已经尝试了所有方法(包括但不限于:仅准备一次,在播放后立即准备,不使用变量,而只

  • } 正如您所看到的,RetryHandler扩展了线程,该线程在内部列表上迭代。尽管使用了和,我还是得到了和已在其他

  • 问题内容: 我正在编写一个JavaScript函数,该函数发出HTTP请求并返回对结果的承诺(但该问题同样适用于基于回调的实现)。 如果我立即知道为该函数提供的参数无效,该函数应该同步还是应该返回被拒绝的Promise(或者,如果您愿意,请使用实例调用回调)? 异步功能应 始终 以异步方式运行(特别是对于错误情况)有多重要?是否确定,如果你知道程序是不是一个合适的状态的异步操作继续进行? 例如:

  • 问题内容: 不久前,我在开发计算机上安装了SQL Server 2008,该计算机已经具有Visual Studio的Sql Server 2005 Express。当我查看程序时,会看到“ Microsoft Sql Server 2008”,其中包含管理工作室等。此外,我还能看到“ MS Sql Server 2005”。 当我在Management Studio 2008中运行查询以选择计算