If I understand your question correctly you’re wonder why you can’t do this:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
showGUI();
}
});
counter.start();
}
The reason why you can’t do it is because the scheduler makes no guarantees… just because you invoked showGUI()
and then you invoked counter.start()
doesn’t mean that the code in showGUI()
will be executed before the code in the run method of the counter
.
Think of it this way:
- invokeLater
starts a thread and that thread isschedules an asynchronous event on the EDT which is tasked with creating theJLabel
. - the counter is a separate thread that depends on the
JLabel
to exists so it can calllabel.setText("You have " + i + " seconds.");
Now you have a race condition: JLabel
must be created BEFORE the counter
thread starts, if it’s not created before the counter thread starts, then your counter thread will be calling setText
on an uninitialized object.
In order to ensure that the race condition is eliminated we must guarantee the order of execution and one way to guarantee it is to execute showGUI()
and counter.start()
sequentially on the same thread:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
showGUI();
counter.start();
}
});
}
Now showGUI();
and counter.start();
are executed from the same thread, thus the JLabel
will be created before the counter
is started.
Update:
Q: And I do not understand what is special about this thread.
A: Swing event handling code runs on a special thread known as the event dispatch thread. Most code that invokes Swing methods also runs on this thread. This is necessary because most Swing object methods are not “thread safe”: invoking them from multiple threads risks thread interference or memory consistency errors. 1Q: So, if we have a GUI why should we start it in a separate thread?
A: There is probably a better answer than mine, but if you want to update the GUI from the EDT (which you do), then you have to start it from the EDT.Q: And why we cannot just start the thread like any other other thread?
A: See previous answer.Q: Why we use some invokeLater and why this thread (EDT) start to execute request when it’s ready. Why it is not always ready?
A: The EDT might have some other AWT events it has to process.
invokeLater
Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI. 2