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

时间:2017-11-10 01:20:17

标签: java multithreading vector synchronization concurrentmodification

我有一个由多个线程操作的ArrayList,由于ArrayList未同步,因此无法正常工作。我按照教授的指示将列表切换为Vector。向量是同步的,但我有与同步相关的异常抛出。

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

例外:

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 个答案:

答案 0 :(得分:5)

你的代码似乎错了。

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

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

答案 1 :(得分:3)

来自docs

  

如果在迭代器之后的任何时间对结构进行了结构修改   以任何方式创建,除非通过迭代器自己删除或添加   方法,迭代器将抛出一个ConcurrentModificationException。

以下代码在封面下创建一个迭代器:

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

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

有不同的选项可以解决它,一种方法是从文件读取到另一个向量,当读取完成时,将另一个向量分配给numbers(因为赋值是原子操作)。请注意,为了让更改对其他主题可见,您需要将numbers声明为volatile