I'm a novice in working with java, and I've only recently reached the concepts of multi-threading and concurrency. What I'm confused about is whether it is wrong practice to have a swing GUI execute without invoking the EDT? I've written the code for a simple application that is heavily dependent on picking up information from a connected database, and when I checked using the SwingUtilities.isEventDispatchThread(), it is not executing in the EDT. Other than some minor lag when sending e-mails, it runs smoothly enough.
My question is should I redesign it to execute inside the EDT, and if I did that, would I have to separate the database part from the EDT?
CodePudding user response:
You do not directly invoke the EDT. It is more that Swing or AWT is run by the EDT. If you want the EDT to do something, use SwingUtilities.invokeLater() to place it in the EDT's queue. Examples are on https://www.javamex.com/tutorials/threads/invokelater.shtml
If the EDT tells you that a button was clicked you can use that opportunity to do whatever - even check something in the database. But do not be surprised when the user perceives a frozen UI while the DB lookup is running.
Thus it is best practice to use the EDT event handlers to trigger new threads for any action that could last more than a few milliseconds, and when these threads want to update the UI they trigger the EDT to work by using SwingUtilities.invokeLater().
Example:
public class Main {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException, TransformerConfigurationException, TransformerException {
JLabel result = new JLabel("<the result will be shown here>");
JButton button = new JButton("Action!");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
button.setEnabled(false); // prevent the user clicking again
new Thread(new Runnable() {
@Override
public void run() {
try {
// lengthy operation takes 10 seconds, performed on a separate thread
Thread.sleep(10L * 1000);
// finished thining. Update UI using the EDT
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
result.setText("Proudly presenting: result!");
}
});
} catch (InterruptedException ex) {
// do nothing on purpose
} finally {
// we are done. Enable the button again through the EDT
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
button.setEnabled(true);
}
});
}
}
}).start();
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(result, BorderLayout.CENTER);
frame.getContentPane().add(button, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
}