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

arraylist上的并发修改

华烈
2023-03-14
public static void removeData(ServiceRequest r) {
    readData();
    ArrayList<ServiceRequest> targets = new ArrayList<ServiceRequest>();
    for (ServiceRequest s : serviceQueue) {  
    //ConcurrentModification Exception triggered on previous line
        if ( 
            s.getClient().getSms() == r.getClient().getSms() && 
            s.getTech().getName().equals(r.getTech().getName()) && 
            s.getDate().equals(r.getDate())) {
                JOptionPane.showMessageDialog(null, s.getClient().getSms() + "'s Service Request with " + s.getTech().getName() + " on " + s.getDate().toString() + " has been removed!");
                targets.add(s);
                System.out.print("targetted"); }
    }
    if (targets.isEmpty()) { System.out.print("*"); }
    else { 
        System.out.print("removed");
        serviceQueue.removeAll(targets); 
        writeData(); }
}
public static void addData(ServiceRequest r) {
    readData();
    removeData(r);
    if (r.getClient().getStatus().equals("MEMBER") || r.getClient().getStatus().equals("ALISTER")) {
        serviceQueue.add(r); } 
    else if (r.getClient().getStatus().equals("BANNED") || r.getClient().getStatus().equals("UNKNOWN")) {
        JOptionPane.showMessageDialog(null, "New Request failed: " + r.getClient().getSms() + " is " + r.getClient().getStatus() + "!", "ERROR: " + r.getClient().getSms(), JOptionPane.WARNING_MESSAGE);
    }
    else {
        int response = JOptionPane.showConfirmDialog(null, r.getClient().getSms() + " is " + r.getClient().getStatus() + "...", "Manually Overide?", JOptionPane.OK_CANCEL_OPTION);
        if (response == JOptionPane.OK_OPTION) {
            serviceQueue.add(r); }
    }
    writeData(); }

public static void readData() {
    try {
        Boolean complete = false;
        FileReader reader = new FileReader(f);
        ObjectInputStream in = xstream.createObjectInputStream(reader);
        serviceQueue.clear();
        while(complete != true) {   
            ServiceRequest test = (ServiceRequest)in.readObject();      
            if(test != null && test.getDate().isAfter(LocalDate.now().minusDays(180))) { 
                serviceQueue.add(test); }
                else { complete = true; }
        }
        in.close(); } 
    catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } 
}
public static void writeData() {
    if(serviceQueue.isEmpty()) { serviceQueue.add(new ServiceRequest()); }
    try {
        FileWriter writer = new FileWriter(f);
        ObjectOutputStream out = xstream.createObjectOutputStream(writer);
        for(ServiceRequest r : serviceQueue) { out.writeObject(r); }
        out.writeObject(null);
        out.close(); }
    catch (IOException e) { e.printStackTrace(); }
}

编辑

这些更改导致并发mod每次触发而不是断断续续地触发,我想这意味着删除代码更好,但现在错误在it.remove();触发

public static void removeData(ServiceRequest r) {
    readData();
    for(Iterator<ServiceRequest> it = serviceQueue.iterator(); it.hasNext();) {
        ServiceRequest s = it.next();
        if ( 
            s.getClient().getSms() == r.getClient().getSms() && 
            s.getTech().getName().equals(r.getTech().getName()) && 
            s.getDate().equals(r.getDate())) {
                JOptionPane.showMessageDialog(null, s.getClient().getSms() + "'s Service Request with " + s.getTech().getName() + " on " + s.getDate().toString() + " has been removed!");
                it.remove();  //Triggers here (line 195)
                System.out.print("targetted"); }
    }
    writeData(); }

线程“awt-eventqueue-0”java.util.concurrentModificatio中的异常nException at java.util.arrayList$itr.checkforcoModification(arrayList.java:901)at java.util.arrayList$itr.next(arrayList.java:851)at data.serviceRequest.removeData(serviceRequest.java:195)at data.serviceRequest.addData(serviceRequest.java:209)<...>

编辑经过更多的搜索,我已经将for循环切换到:

        Iterator<ServiceRequest> it = serviceQueue.iterator();
        while(it.hasNext()) {

又回到了间歇性触发。我的意思是,当我第一次尝试导入数据时(removeData方法是从addData方法触发的),它会触发并发mod异常,但下一次尝试时,它会推过失败并转移到另一个文件。我知道有很多这些并发的mod问题,但我没有找到任何对我的情况有帮助的东西,所以链接到其他答案是非常受欢迎的...

共有1个答案

陶宜民
2023-03-14

这不是怎么做的,在遍历列表时删除元素,您使用迭代器。像这样:

List<ServiceRequest> targets = new ArrayList<ServiceRequest>();
for(Iterator<ServiceRequest> it = targets.iterator(); it.hasNext();) {
    ServiceRequest currentServReq = it.next();
    if(someCondition) {
        it.remove();
    }
}

如果只有一个线程,则不会以这种方式获得ConcurrentModificationException。

如果代码中涉及多个线程,则仍可能获得ConcurrentModificationException。解决这个问题的一种方法是使用collections.synchronizedCollection(...)因此,您将获得一个不会产生ConcurrentModificationException的同步集合。但是,您的代码可能会变得非常慢。

 类似资料:
  • 问题内容: 我正在用Java创建一个多线程聊天。当用户u1向用户u2发送消息但未连接用户u2时,用户u1将消息发送至服务器,而用户u2一旦连接至服务器,便会收到该消息。未发送的消息将添加到ArrayList中。连接用户后,他会检查自己是否是未决邮件的收件人。如果是,则将邮件发送给他,然后将其从待处理邮件列表中删除。这是我的方法: 这就是我得到的: 我如何解决它?是因为我正在使用迭代器吗? 问题答案

  • 当我使用temp=iterator.next()时,sort方法会导致并发修改错误。你能帮我解决并发修改错误吗。我给出了整个类的代码,但我只是尝试完成sort方法。事先谢谢你的帮助。 我必须对ArrayList中的所有数组进行排序。

  • 问题内容: 问题发生在 包含该行的代码位于 所有这一切都在里面,这里是一个 当我触摸时,它可能会激活,这将创建另一个具有不同属性的属性,这些属性会从屏幕上掉下来并在不到一秒钟的时间内销毁自己。这是我创建粒子效果的方式。我们可以将其称为“粒子” ,就像构造函数中的参数一样。 一切正常,直到我添加另一个main为止。现在,我同时在屏幕上有两个,如果我触摸最新的,它可以正常工作并启动粒子。 但是,如果我

  • 问题内容: 我知道这不是线程安全的,但是我不确定其确切含义。 在和都使用的情况下,以下哪种情况会引起问题并需要同步? 两个线程同时读取相同的索引 假设您不在乎获取旧元素还是新元素,则替换尝试同时访问的元素。 问题答案: 两个线程同时读取相同的索引 如果 列表是由分支and 的线程构造的,并且列表在线程被分支之前已完全构建并加载,则可以从公共线程读取多个线程。 这样做的原因是,使用线程和派生该线程的

  • 我正在阅读关于WeakHashMap的Java文档,我得到了基本概念。由于GC线程在后台运行,因此可能会出现“异常行为”,例如在迭代时出现ConcurrentModificationException等。 我不明白的是,如果默认实现没有同步,并且没有以任何方式包含锁,那么为什么不可能得到不一致的状态呢。假设你有两条线。GC线程在某个索引处删除某个键,同时,在同一索引处,用户线程在数组中插入一个键值

  • 问题内容: 我有这段代码,它给了我并发修改异常。即使看不到任何并发修改,我也无法理解为什么继续得到它。 问题答案: 为了避免,你应该这样编写代码: 允许你在迭代期间修改列表,但不能在创建和使用列表之间进行修改。