Исключение одновременной модификации в Swingworker

Я создал программу для чтения последовательного порта, построения данных и отображения значения. Я использую SwingWorker для сбора, проверки и построения графиков значений, позволяя пользователю остановить сбор данных в графическом интерфейсе. Я считаю, что получаю исключение модификации, когда пытаюсь построить значение, а также показать точное значение.

Ниже представлена ​​упрощенная версия doInBackground(). Строки, которые я стер, по сути, проверяют и сравнивают прочитанное значение.

protected Integer doInBackground() 
    while (true && !isCancelled()) {
        value = initandReadCOM();
        // I also check and compare the value
        publish(value);
    }
    return 0;
}

Затем я использую команду process для построения данных. Ближайшая ветка по этой проблеме, которую я смог найти, предложила использовать это.

@Override
protected void process(List<Float> chunks) {
    super.process(chunks);
    float factor = chunks.get(chunks.size() - 1);
    seriesUpdated = getSeries();
    SetDataField(factor);
    this.seriesUpdated.add(new Millisecond(), factor);
}

Методы SetDataField и seriesUpdated перечислены ниже, если они необходимы для диагностики проблемы.

public void SetDataField(float n) {
        this.data_.setText("Data: " + String.valueOf(n));
}

public TimeSeries getSeries() {
        return this.series;
}

По мере того, как программа работает в течение более длительного периода времени, это исключение начинает проявляться чаще. Любая помощь будет принята с благодарностью.

Кроме того, пожалуйста, дайте мне знать, если вам нужно увидеть что-то еще, чтобы помочь. Спасибо

РЕДАКТИРОВАТЬ: Ниже приведена трассировка стека

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at java.util.Collections$UnmodifiableCollection$1.next(Unknown Source)
    at org.jfree.chart.plot.XYPlot.drawRangeMarkers(XYPlot.java:4088)
    at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3281)
    at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1226)
    at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1612)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
    at javax.swing.RepaintManager.paint(Unknown Source)
    at javax.swing.JComponent._paintImmediately(Unknown Source)
    at javax.swing.JComponent.paintImmediately(Unknown Source)
    at javax.swing.RepaintManager$3.run(Unknown Source)
    at javax.swing.RepaintManager$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$1000(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

person user2755399    schedule 24.10.2013    source источник
comment
можете ли вы опубликовать трассировку стека исключения   -  person exexzian    schedule 24.10.2013
comment
Исключения параллелизма возникают, когда вы изменяете какой-либо объект данных, когда другой объект данных читает его. Один из способов выяснить, где у вас возникли такие проблемы, - использовать ключевое слово synchronized в ваших методах, которые редактируют/читают из вашего объекта данных. Хотя это не всегда правильный способ решения проблемы, он, по крайней мере, может помочь вам выяснить, где именно возникает проблема. См. docs.oracle.com/javase/tutorial/essential/concurrency/< /а>.   -  person Chill    schedule 24.10.2013
comment
Вы где-то повторяете свой массив, а затем пытаетесь его изменить? поскольку показанный вами код не включает эту часть   -  person exexzian    schedule 24.10.2013
comment
В doInBackground я умножаю значение на коэффициент преобразования единиц измерения. У меня также (забыл упомянуть) есть вторая публикация, если система не может расшифровать значение, которое было красным. Но если вы спрашиваете о методе process(), то нет, метод process() был скопирован непосредственно из кода. я   -  person user2755399    schedule 24.10.2013
comment
Вы изменяете модель данных JFreeChart, в то время как он может получить доступ к этой модели из потока пользовательского интерфейса, чтобы нарисовать ее. Так что конфликт очевиден.   -  person Holger    schedule 24.10.2013
comment
@Holger, спасибо за ответ. Как исправить конфликт?   -  person user2755399    schedule 24.10.2013


Ответы (1)


Вы изменяете модель данных JFreeChart, в то время как он может получить доступ к этой модели из потока пользовательского интерфейса, чтобы нарисовать ее. Чтобы исправить это, у вас есть разные варианты:

  1. Пусть фоновый поток вычисляет и сохраняет результаты в Collections независимо от модели JFreeCharts. Затем обновите модель в потоке пользовательского интерфейса. Это самый простой подход, когда модель диаграммы рассматривается как часть пользовательского интерфейса, но в конечном итоге вы все равно можете выполнять много работы в потоке пользовательского интерфейса.

  2. Используйте несколько моделей диаграмм. Обновите модель диаграммы, отличную от используемой в настоящее время отображаемой диаграммой. Затем обновите пользовательский интерфейс, установив новую модель на графике в потоке пользовательского интерфейса. Это позволяет выполнять определенные вычисления, относящиеся к диаграмме, в фоновом потоке и может быть реализовано с минимальным количеством изменений в вашем текущем коде. Но это может оказаться неэффективным, если у вас есть довольно небольшие добавочные изменения, поскольку вся модель диаграммы пересчитывается при каждом обновлении.

  3. Переместите весь код диаграммы в фоновый поток. Возможно, это самое радикальное изменение, но и самое эффективное решение. В этом решении поток пользовательского интерфейса больше не обращается к диаграмме и ее модели (или только в том случае, если фоновый поток точно не запущен). Вместо этого весь расчет диаграммы и рендеринг выполняются внутри фонового потока в файле BufferedImage. Поток пользовательского интерфейса будет выполнять рисование, просто выводя ранее отрендеренное изображение на экран. Обновление/синхронизация между пользовательским интерфейсом и фоновым потоком состоит только из поменять местами два изображения.

  4. Используйте блок Lock или synchronized, чтобы фоновый поток и поток пользовательского интерфейса обращались к модели только в разное время. Поскольку ваша фоновая угроза состоит только из обновления модели, это фактически равносильно полному отсутствию многопоточности. Я просто добавил эту опцию для полноты...

person Holger    schedule 25.10.2013
comment
Спасибо за объяснение. Однако из-за моего статуса новичка я не знаю, как реализовать эти предложения. Есть ли пример или скелетный код, на который я могу посмотреть? Еще раз спасибо за ваши комментарии. - person user2755399; 25.10.2013