具有 ConcurrentModificationException 的 Java 线程

标签 java multithreading exception arraylist concurrentmodification


我目前正在开发我的第一个多线程软件 - 一个计算素数的程序......
基本上我创建了n(线程数)个可运行对象。这些可运行对象被添加到 ArrayList 中。他们检查一个数字是否是素数。如果该数字是质数,我会将其添加到一个长数组中以供以后使用。由于我希望素数在该数组中处于正确的顺序,因此我需要特定的线程来等待其他线程。我通过循环遍历 ArrayList(见上文)并等待线程来完成此操作,该线程检查较小的数字。
线程完成后,我想从给定的 ArrayList 中删除它,但我不能,因为其他线程仍在循环它(我猜这就是发生 ConcurrentModificationException 的原因 - 这是我第一次使用线程...)。


老实说,我希望你们中的任何人都可以帮助我:)
非常感谢您!

马蒂亚斯

我的可运行类(我只是在主方法中创建了该类的四个对象):

导入java.util.ArrayList;

public class PrimeRunnable implements Runnable {

    //Static Util
    public static ArrayList<PrimeRunnable> runningThreads = new ArrayList<PrimeRunnable>();
    public static long[] primes;
    public static int nextFreeIndex = 1;
    public static long nextPossiblePrime = 3;

    //Object specific
    private long numberToCheck;
    private Thread primeThread;
    private String threadName;
    private long threadID;

    public PrimeRunnable() {
        numberToCheck = nextPossiblePrime;
        increaseNextPossiblePrime();

        threadName = "ThreadToCheck" + numberToCheck;
        threadID = numberToCheck;

        runningThreads.add(this);
    }

    @Override
    public void run() {
        boolean isPrime = true;
        double sqrtOfPossiblePrime = Math.sqrt(numberToCheck);

        long lastDevider = 0;

        for(int index = 0; index < nextFreeIndex; index++) {
            lastDevider = primes[index];
            if(numberToCheck%primes[index] == 0) {
                isPrime = false;
                break;
            }
            if(primes[index] > sqrtOfPossiblePrime) {
                break;
            }
        }

        while(lastDevider < sqrtOfPossiblePrime) {
            lastDevider += 1;

            if(numberToCheck%lastDevider == 0) {
                isPrime = false;
                break;
            }
        }

        if(isPrime) {
            //Wait for lower Threads.

            for(PrimeRunnable runnable : runningThreads) {
                if(runnable.getThreadID() < this.getThreadID()) {
                    try {
                        runnable.primeThread.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

            primes[nextFreeIndex] = numberToCheck;
            increaseNextFreeIndex();
            System.out.println(numberToCheck);
        }
        runningThreads.remove(this);
    }

    public void start() {
        if(primeThread == null) {
            primeThread = new Thread(this, threadName);
        }

        primeThread.start();
    }

    public void reset() {
        numberToCheck = nextPossiblePrime;
        increaseNextPossiblePrime();

        threadName = "ThreadToCheck" + numberToCheck;
        threadID = numberToCheck;

        //No need to readd into runningThread, since we only manipulate an already existing object.
        primeThread = new Thread(this, threadName);
        primeThread.start();
    }

    public static void setUpperBorder(int upperBorder) {
        if(primes == null) {
            primes = new long[upperBorder];
            primes[0] = 2;
        } else {
            System.err.println("You are not allowed to set the upper border while running.");
        }
    }

    public long getNumberToCheck() {
        return numberToCheck;
    }

    private void increaseNextPossiblePrime() {
        nextPossiblePrime += 2;
    }

    private void increaseNextFreeIndex() {
        nextFreeIndex += 2;
    }

    public long getThreadID() {
        return threadID;
    }

    public boolean isAlive() {
        return primeThread.isAlive();
    }
}

最佳答案

我能够复制该问题并使用并发列表的 Java 实现来修复它 CopyOnWriteArrayList

这是我的主课

public class PrimeRunnableMain {

    public static void main(String[] args) {
        PrimeRunnable.setUpperBorder(10);
        PrimeRunnable primeRunnable1 = new PrimeRunnable();
        PrimeRunnable primeRunnable2 = new PrimeRunnable();
        PrimeRunnable primeRunnable3 = new PrimeRunnable();
        PrimeRunnable primeRunnable4 = new PrimeRunnable();
        primeRunnable1.start();
        primeRunnable2.start();
        primeRunnable3.start();
        primeRunnable4.start();
    }
}

这里是 PrimeRunnable

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class PrimeRunnable implements Runnable {

    // Static Util
    public static List<PrimeRunnable> runningThreads = new CopyOnWriteArrayList<PrimeRunnable>();
    public static long[] primes;
    public static int nextFreeIndex = 1;
    public static long nextPossiblePrime = 3;

    // Object specific
    private long numberToCheck;
    private Thread primeThread;
    private String threadName;
    private long threadID;

    public PrimeRunnable() {
        numberToCheck = nextPossiblePrime;
        increaseNextPossiblePrime();

        threadName = "ThreadToCheck" + numberToCheck;
        threadID = numberToCheck;

        runningThreads.add(this);
    }

    @Override
    public void run() {
        boolean isPrime = true;
        double sqrtOfPossiblePrime = Math.sqrt(numberToCheck);

        long lastDevider = 0;

        for (int index = 0; index < nextFreeIndex; index++) {
            lastDevider = primes[index];
            if (numberToCheck % primes[index] == 0) {
                isPrime = false;
                break;
            }
            if (primes[index] > sqrtOfPossiblePrime) {
                break;
            }
        }

        while (lastDevider < sqrtOfPossiblePrime) {
            lastDevider += 1;

            if (numberToCheck % lastDevider == 0) {
                isPrime = false;
                break;
            }
        }

        if (isPrime) {
            // Wait for lower Threads.

            for (PrimeRunnable runnable : runningThreads) {
                if (runnable.getThreadID() < this.getThreadID()) {
                    try {
                        runnable.primeThread.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

            primes[nextFreeIndex] = numberToCheck;
            increaseNextFreeIndex();
            System.out.println(numberToCheck);
        }
        runningThreads.remove(this);
    }

    public void start() {
        if (primeThread == null) {
            primeThread = new Thread(this, threadName);
        }

        primeThread.start();
    }

    public void reset() {
        numberToCheck = nextPossiblePrime;
        increaseNextPossiblePrime();

        threadName = "ThreadToCheck" + numberToCheck;
        threadID = numberToCheck;

        // No need to readd into runningThread, since we only manipulate an
        // already existing object.
        primeThread = new Thread(this, threadName);
        primeThread.start();
    }

    public static void setUpperBorder(int upperBorder) {
        if (primes == null) {
            primes = new long[upperBorder];
            primes[0] = 2;
        } else {
            System.err
                    .println("You are not allowed to set the upper border while running.");
        }
    }

    public long getNumberToCheck() {
        return numberToCheck;
    }

    private void increaseNextPossiblePrime() {
        nextPossiblePrime += 2;
    }

    private void increaseNextFreeIndex() {
        nextFreeIndex += 2;
    }

    public long getThreadID() {
        return threadID;
    }

    public boolean isAlive() {
        return primeThread.isAlive();
    }
}

关于具有 ConcurrentModificationException 的 Java 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30683070/

相关文章:

java - 显式转换如何执行

java - 快速写入 JEditorPane

ruby - ruby 的 ensure 什么时候不会运行?

java - 当我在 ControllerAdvice 中有 RuntimeException 的 ExceptionHandler 时,spring AccessDeniedHandler 接口(interface)不会被调用?

java - Java 发送电子邮件时出现异常

java - 将 XSLT 2.0 函数 iri-to-uri 替换为来自通过 Java 传入的参数的 URI 列表

java - 如何使用java删除或隐藏Http响应错误

java - 使用 Jmeter 对登录功能进行一些测试后,在范围内找不到 bean userList

c# - 在 UI 线程上报告后台线程进度

Java:这是否正确暂停线程?