线程抛出java.util.ConcurrentModificationException

时间:2018-12-10 12:23:24

标签: java multithreading exception javafx arraylist

每次我运行程序时,该线程都会引发此异常,而我似乎找不到原因。有人可以解释一下发生这种情况的原因吗?

package GPS.gpsproject;

import GPS.Model.Event;
import GPS.Model.Vehicle;

import java.time.Duration;
import java.time.LocalDate;

import java.util.List;


public class Notify extends Thread {
    private List<Veiculo> vehicles;
    private Controler controler;

    public Notify(List<Veiculo> vehicles, Controlador controler) {
        this.controler= controler;
        this.vehicles= vehicles;   
    }

    @Override
    public void run() {
        while (true) {
            for (Vehicle v : vehicles) {
                for (Event e : v.getEvents()) {
                    if (Duration.between(e.getData().atStartOfDay(), LocalDate.now().atStartOfDay()).toDays() < e.getDiasAntes() && !e.isNotified()) {
                        e.setNotified(true);
                        controler.sendNotification("Notification", e.getDesc());

                }
            }
        }
    }
}

还有一个例外:

Exception in thread "Thread-4" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at GPS.gpsproject.Notifica.run(Notify.java:25)

sendNotification()方法只是将事件通知用户

2 个答案:

答案 0 :(得分:1)

当thread1使用

对其进行迭代时,thread2修改了ArrayList(例如,添加新元素)。

for (Vehicle v : vehicles)

thread1将抛出ConcurrentModificationException,这称为快速失败。

您可能要使用CopyOnWriteArrayList

  

此数组在迭代器的生存期内从未更改,因此   干扰是不可能的,并且保证迭代器不会抛出   ConcurrentModificationException。迭代器不会反映   自迭代器以来,对列表的添加,删除或更改   已创建。

答案 1 :(得分:0)

我假设NotificaNotify指的是同一个班级(其中一个必须是错字)。您正在将List<Veiculo>传递给Notifica类的构造函数。然后,您可以在List方法中遍历那个run()

假设您在嵌套的for循环内调用的方法未修改vehicles列表或Event的任何内部集合,这意味着其他一些线程必须在其中进行结构更改遍历这些集合时的其中一个。

由于vehicles不应在结构上进行修改,因此可能的解决方案是在构造函数中创建一个副本:

this.vehicles = new ArrayList<>(vehicles);  

请注意,这仅在其他线程未对属于Event实例的Veiculo的内部集合进行结构更改的情况下有效,因为这是一个浅表副本。