Using the synchronized keyword on a method allows only one thread at a time to execute that method, but the EDT can process multiple "events" that will be running in that method concurrently. See sample code below for a demonstration. When you click the test button, the output is:
0 before dialog, EDT=true
1 before dialog, EDT=true
(click OK button for 1 here)
1 after dialog, EDT=true
(click OK button for 0 here)
0 after dialog, EDT=true
What I'm looking for is a way to only allow one EDT event to be active in the test() method at a time, so that the output would be
0 before dialog, EDT=true
(click OK button for 0 here)
0 after dialog, EDT=true
1 before dialog, EDT=true
(click OK button for 1 here)
1 after dialog, EDT=true
Seems like someone must have solved this problem before. I think it would be possible to write some kind of locking object to use at the beginning of the method, or to wrap the method, but being lazy, would rather not reinvent the wheel.
My test case:
package test1;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class EDTSyncTest extends javax.swing.JFrame {
private static final Object locker = new Object();
private int counter;
public EDTSyncTest() {
initComponents();
}
private synchronized void test() {
int l_id = counter++;
logit("" + l_id + " before dialog, EDT=" + SwingUtilities.isEventDispatchThread());
JOptionPane l_pane = new JOptionPane("test id " + l_id);
JDialog l_diag = l_pane.createDialog(this, "test");
l_diag.setModal(true);
l_diag.setVisible(true);
logit("" + l_id + " after dialog, EDT=" + SwingUtilities.isEventDispatchThread());
}
private void startTest() {
new Delayer().execute();
test();
}
private static void logit(String a_msg) {
System.out.println(a_msg);
}
private class Delayer extends SwingWorker<Object, Object> {
@Override
protected Object doInBackground() throws Exception {
Thread.sleep(2000);
return null;
}
@Override
protected void done() {
test();
}
}
private void initComponents() {
jButton1 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new java.awt.FlowLayout());
jButton1.setText("Test");
jButton1.setName("jButton1"); // NOI18N
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
getContentPane().add(jButton1);
pack();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
startTest();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new EDTSyncTest().setVisible(true);
}
});
}
protected javax.swing.JButton jButton1;
}