【问题标题】:ConcurrentModificationException when using iter.hasNext() [closed]使用 iter.hasNext() 时出现 ConcurrentModificationException [关闭]
【发布时间】:2016-02-20 20:12:39
【问题描述】:

我有一个producer consumer 设置,使用Wildfly AS for JMS,生产者每1分钟使用一次newFixedThreadPool(126),每个线程从REST服务中提取数据并推送它到HornetQWildfly AS 上。

然后在消费者方面,我有一个消费者类,它使用 HornetQ 中的消息和一个简单的 Parser 类,对于数据库插入,我正在尝试缓冲数据库插入并且我得到一个异常在线程“main”中 java.util.ConcurrentModificationException 我怀疑这与我的代码不是线程安全有关,但我无法缩小范围。

消费者:

    public void Consume(Consumer asyncReceiver) throws Throwable {

        try (javax.jms.Connection connection = connFactory.createConnection(props.getProperty("DEFAULT_USERNAME"), props.getProperty("
             Session queueSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

             MessageConsumer msgConsumer = queueSession.createConsumer(queue)) {

            msgConsumer.setMessageListener(asyncReceiver);

            connection.setExceptionListener(asyncReceiver);

            connection.start();

            /** I think this is causing the problem */
            System.out.println("waiting for messages");
            int bufferCount = 0;
            for (int i = 0; i < 47483647; i++) {
                Thread.sleep(1000);
                System.out.print(".");
                if (bufferCount == 5) {
                    if(responseList.size() > 50){
                        this.buffer();
                    }
                    bufferCount = 0;
                }
                bufferCount++;
            }
            System.out.println();
        }

    } catch (Exception e) {
        log.severe(e.getMessage());
        throw e;
    } finally {
        if (context != null) {
            context.close();
        }
    }
    if (connection != null) {
        connection.close();
    }
}

public void buffer() throws Exception {
        System.out.println("Parsing: " + responseList.size() + " messages");
        Parser parser = new Parser();
        parser.addList(responseList);
        parser.parseApplication();
        responseList.clear();
}

@Override
public void onMessage(Message message) {
    TextMessage msg = (TextMessage) message;
    try {
        responseList.add(msg.getText());
    } catch (Exception e) {
        e.printStackTrace();
    }

解析器:

public class Parser {

private ArrayList<String> responseList;


public void addList(ArrayList<String> list) {
    this.responseList = list;
}

public void parseApplication() throws Exception {

    DBConnection db = DBConnection.createApplication();

    try (Connection connection = db.getConnection()) {

//Code removed for stack question

        Iterator<String> iter = responseList.iterator();
        while(iter.hasNext()) {

// This is where the error is thrown 
            while (fieldsIterator.hasNext()) {

            //Cut code from here, basic JSON parsing done here
               timeslices = parse(iter.Next())

                for (int i = 0; i < timeslices.length(); i++) {

                        ThroughputEntry TP = new ThroughputEntry();
                        TP.setThroughput(values.getDouble(name));
                        TP.setEnvironment(envName);
                        TP.setName(appName);
                        TP.setRetrieved(from);
                        TP.setPeriodEnd(to);
                        db.addHistory(TP);
                    }
                }
            }
        }
        iter.remove();
    }
}
}

也许我应该把我的缓冲方法变成threadpool

【问题讨论】:

  • 哇...这里有很多代码,但问题中没有明确的信息说明错误发生在代码中的确切位置。你能把它清除并减少代码量吗?
  • 这是一个代码转储。请发minimal reproducible example
  • 我已经清理了代码,我不确定问题出在哪里。

标签: java multithreading arraylist


【解决方案1】:
responseList.add(msg.getText());

在您的解析器迭代列表时修改列表。 在这种情况下,迭代器会抛出 ConcurrentModificationException。 要修复它,您应该在解析之前复制列表。

【讨论】:

  • 我尝试在Parser 类中复制列表,我得到了同样的错误,错误是在Parser 类中抛出的
  • 编辑后没有更多代码会导致错误。
  • 我认为错误是由剩下的代码引起的,我在某处遗漏了一些东西。
  • 你说得对,我忘了我需要用ArrayList 做一个浅拷贝,新手错误,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
  • 1970-01-01
  • 1970-01-01
  • 2018-01-09
相关资源
最近更新 更多