Current situation:
The chart will be kept redrawing as dataset will be updated as time goes by.
At the same time, the collection of markers may be updated on demand.
On very rare case, it would throw "ConcurrentModificationException" when XYPlot is iterating the markers during drawing if marker is added at that time.
Just see if it is necessary to synchronize the collection ?
Or should notify the chart to stop drawing the plot until the marker is added? (which methods should be called)
Thanks for your advice.
ConcurrentModificationException when XYPlot drawing markers
-
- Posts: 3
- Joined: Tue Feb 15, 2011 2:40 pm
- antibot: No, of course not.
Re: ConcurrentModificationException when XYPlot drawing markers
I too have a problem in this regard... here's the essence of a stack trace I see from time to time:
I am extending ChartPanel and I have tried loads of different tactics including wrapping the annotations list in a SynchronizedList and using that for locking and access, for each method that makes any changes to the plot, using ReentrantLock, adding 'synchronized' in the signature and lately synchronizing on the plot object.
The exception I see is always the same, calling drawAnnotations from an awt.EventDispatchThread. Does anyone have some idea of what I can implement to prevent this?
TIA, Mike Watts
Code: Select all
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at org.jfree.chart.plot.XYPlot.drawAnnotations(XYPlot.java:3981)
at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3385)
....
at java.awt.EventDispatchThread.run(EventDispatchThread.java:136)
The exception I see is always the same, calling drawAnnotations from an awt.EventDispatchThread. Does anyone have some idea of what I can implement to prevent this?
TIA, Mike Watts
-
- Posts: 3
- Joined: Tue Feb 15, 2011 2:40 pm
- antibot: No, of course not.
Re: ConcurrentModificationException when XYPlot drawing markers
As this has a very complicated answer and no-one else saw fit to provide even a pointer, I thought I'd document some notes and a solution for any poor souls with the same problem in the future.
First some background, the process used in my case, some recommended reading and a solution.
You probably know this already, as I did, that this is not a 'JFreeChart' thing but a 'Swing' thing... but because JFreeChart is a much more complex beast than most swing components used in daily life it is more likely to happen with this [sort of] component. I also knew it was a multiple-thread issue, just not how to synchronize with the swing thread.
The setup I have is complex: multiple threads monitoring an engineering process which is asynchronous to the program. Events are raised by these threads using a typical EventListener interface being sent an EventObject from the 'monitor'. The event listener processes the data and adds a new point to the chart ( and is the only publicly used method in the 'graph' class ). So the problem then was that the 'monitor' thread was occasionally updating the chart whilst the Swing thread was doing something itself ( not sure what to be honest ).
After some research I came to understand I needed to link into the AWT event dispatching thread and found a couple of useful articles:
http://java.sun.com/products/jfc/tsc/ar ... eads1.html
http://java.sun.com/products/jfc/tsc/ar ... eads2.html
Having a quick look at the second, which describes the SwingWorker and a link to the source code, I decided that this was not the best way to go in this case, but ( interestingly ) the SwingWorker makes a call to SwingUtilities.invokeLater(), described more fully in the first article, which looks like the ticket.
So - my solution looks like this:
The 'final' keyword in the argument list is required.
I hope this helps someone!
First some background, the process used in my case, some recommended reading and a solution.
You probably know this already, as I did, that this is not a 'JFreeChart' thing but a 'Swing' thing... but because JFreeChart is a much more complex beast than most swing components used in daily life it is more likely to happen with this [sort of] component. I also knew it was a multiple-thread issue, just not how to synchronize with the swing thread.
The setup I have is complex: multiple threads monitoring an engineering process which is asynchronous to the program. Events are raised by these threads using a typical EventListener interface being sent an EventObject from the 'monitor'. The event listener processes the data and adds a new point to the chart ( and is the only publicly used method in the 'graph' class ). So the problem then was that the 'monitor' thread was occasionally updating the chart whilst the Swing thread was doing something itself ( not sure what to be honest ).
After some research I came to understand I needed to link into the AWT event dispatching thread and found a couple of useful articles:
http://java.sun.com/products/jfc/tsc/ar ... eads1.html
http://java.sun.com/products/jfc/tsc/ar ... eads2.html
Having a quick look at the second, which describes the SwingWorker and a link to the source code, I decided that this was not the best way to go in this case, but ( interestingly ) the SwingWorker makes a call to SwingUtilities.invokeLater(), described more fully in the first article, which looks like the ticket.
So - my solution looks like this:
Code: Select all
public void handleEvent(final InterestingEvent ev) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
graph.addPoint(ev.getX(), ev.getY());
}
});
}
I hope this helps someone!