2013-10-24 40 views
0

我创建了一个程序来读取串行端口,绘制数据,并显示值。我正在使用SwingWorker来收集,检查和绘制这些值,同时允许用户在GUI中停止数据收集。当我尝试绘制该值并显示确切值时,我相信我正在接受修改异常。并行修改异常在摇摆工

下面是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); 
} 

SetDataFieldseriesUpdated方法如下表所示(如果需要),以帮助诊断问题。

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) 
+0

你可以发布,当你正在修改的时候另一个数据对象被读取它的一些数据对象异常 – exexzian

+1

并发异常的堆栈跟踪发生。找出你遇到这种问题的一种方法是在你的数据对象编辑/读取的方法中使用'synchronized'关键字。虽然这并不总是解决问题的正确方法,但它至少可以帮助您找出问题的确切位置。请参阅http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html。 – Chill

+1

你是否在迭代你的数组列表然后尝试修改它?因为您显示的代码不包含该部分 – exexzian

回答

0

您正在修改的JFreeChart的数据模型,虽然它可能来自访问,以画它的UI线程内的模型。为了解决这个问题,你有多种选择:

  1. 让后台线程计算和存储结果到Collection自主从JFreeChart S模式。然后在UI线程内更新模型。这是最直接的方法,将图表模型看作是UI部分,但是您最终可能还是要在UI线程中做很多工作。

  2. 使用多个图表模型。更新与当前渲染图表使用的图表模型不同的图表模型。然后通过在UI线程内的图表上设置新模型来更新UI。这允许某些图表特定的计算在后台线程中运行,并且可以通过对当前代码进行的最小数量的更改来实现。但是,如果您的增量更改较小,则整个图表模型在每次更新时都会重新计算,这可能会导致效率低下。

  3. 将整个图表代码移到后台线程中。这可能是最根本的改变,但是最有效的解决方案。在此解决方案中,图表及其模型不再由UI线程访问(或仅在确定后台线程不运行时)。相反,整个图表计算和渲染都是在后台线程内完成的,其格式为BufferedImage。 UI线程将通过将先前渲染的图像粘贴到屏幕来进行绘制。 UI和后台线程之间的更新/同步仅包含swapping这两个图像。

  4. 使用Lock或​​块可以确保背景和UI线程都在不同的时间访问模型。由于你的背景威胁只包含模型更新,所以这实际上就像没有多线程一样。我只是说这个选项的完整性......

+0

谢谢你的解释。但是,由于我的初学者地位,我不知道如何实施这些建议。是否有我可以看到的示例或框架代码?再次感谢您的评论。 – user2755399