Reputation: 1757
My GUI application has methods that [re-]load data for JTable
instances (like eg File->New
, File->Open
menu items). When items are being loaded or emptied, the event listeners are active and start handling objects in an undefined state, hence raising exceptions and conflicting with the loading operation.
I want to stop the listeners during loading operations. So I thought one solution would be making both the loading and the listener methods synchronized
.
What I have is a few instances of JTable
, and the listener is a TableModelListener
. So, for example, when File->New
is clicked, it fires this method:
private synchronized void newFileClicked() {
// empty all tables in the application
}
And in the conflicting listener:
class MyModelListener implements TableModelListener {
@Override public void tableChanged(TableModelEvent tme) {
synchronized (this) {
// do stuff
}
}
}
But still, when the newFileClicked
method is called, simultaneous output from this and the tableChanged
methods occur.
Is my understanding of synchronized
wrong? Or is this implementation not correct?
May be both ?=/
edit: corrected implementation after this answer also has the same symptom
Object lock = new Object();
private void newFileClicked() {
synchronized (lock) {
// empty all tables in the application
}
}
class MyModelListener implements TableModelListener {
@Override public void tableChanged(TableModelEvent tme) {
synchronized (lock) {
// do stuff
}
}
}
// Still does not work ! =/
Upvotes: 0
Views: 213
Reputation: 324157
System level events (like MouseEvents or KeyEvents) are added to the end of the Event Dispatch Thread (EDT) and are processed sequentially.
Swing level events (like the TableModelEvent) are processed at the time the event is generated. That is the event is NOT added to the EDT.
I want to stop the listeners during loading operations.
You need to do something like:
Or you could use a a boolean variable like "loading" and then have each of the listeners check if you are currently "loading" and if so, skip the processing.
Upvotes: 1
Reputation: 147154
You appear to be using synchronized
on different objects. synchronized
will only block if a lock is held on exactly the same object.
In fact, Swing is super thread-hostile. Restrict usage to the AWT Event Dispatch Thread (EDT) - use java.awt.EventQueue.invokeLater
. If you need other threads, make sure they don't touch anything Swing. Copy data to and from the EDT on the EDT.
Upvotes: 0