What's New Runnable () {}?
new Runnable() { public void run() { createAndShowGUI(); } };
This declares an anonymous class and instantiates a new instance. This is basically equivalent to this:
class Creator implements Runnable { public void run() { createAndShowGUI(); } } new Creator();
Prior to Java 8 lambdas, an anonymous class is a way to make some kind of functional programming. Passing Runnable to invokeLater similar to passing a function that EDT can do later when it wants (by calling run on it).
What does invokeLater do with runnable?
Initially, all he does is create an event for his wrapper ( InvocationEvent ) and put it at the end of the queue.
After the sequence of events, invokeLater notifies EDT (which wakes up if it is waiting). The EDT native start method is an endless loop that processes events. It looks something like this (very rephrased):
public void run() { while(true) { EventQueue eq = getEventQueue(); synchronized(eq) { while(eq.hasNextEvent()) { processOneEvent(eq.getNextEvent()); } try { eq.wait(); } catch(InterruptedException ie) {} } } }
When the EDT hits the new InvocationEvent, it calls run in Runnable, which calls createAndShowGUI .
So passing Runnable to invokeLater or invokeAndWait allows you to run whatever code you want on the EDT.
How soon is the call made?
In most cases, immediately or almost immediately. EDT is very responsive. The "later" part of "invokeLater" is just a hint that:
run runs asynchronously. The thread that invokeLater calls can continue the call before the event is processed.- Other events may be handled first.
Of course, invokeAndWait exists as an alternative if a synchronous call to run is required. (Although it should be noted that invokeAndWait may also result in other events being processed if they were queued before the new InvocationEvent.)
Asynchronous
SwingUtilities.invokeLater(new Runnable() { public void run() { System.out.println("hello"); } }); System.out.println("world");
It can print
hello
world
and he can print
world
hello
because the calling thread may or may not continue until (or even while) the event is being processed. It depends on the system thread scheduler.
Synchronous
SwingUtilities.invokeAndWait(new Runnable() { public void run() { System.out.println("hello"); } }); System.out.println("world");
It will definitely print
hello
world
because the calling thread will wait for run to complete before it continues (unless an exception is thrown).
invokeAndWait uses a wait and notification scheme to achieve this. A monitor object is created and assigned to an InvocationEvent. invokeAndWait calls wait after the event is dispatched, and InvocationEvent notifyAll calls after run end in the EDT. The wait and notification scheme is the reason invokeAndWait cannot be called on the EDT. EDT cannot stop in the middle of one event to handle another.
What happens if more than one event is queued?
The EDT processes events one at a time, in order of priority and according to their priority. Some events can also be combined (a regular InvocationEvent will not). Most events are a normal priority. A PaintEvent (such as a repaint call) usually has low priority, and some system events have higher priorities.
In the specific example that you specified:
SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); SwingUtilities.invokeLater(new Runnable() { public void run() { doSomethingElse(); } });
Since they are the same event and the same priority, the doSomethingElse event will be processed after the createAndShowGUI event createAndShowGUI .
Similarly, if something like this was done:
SwingUtilities.invokeLater(new Runnable() { public void run() { SwingUtilities.invokeLater(new Runnable() { public void run() { System.out.println("world"); } }); System.out.println("hello"); } });
It will print
hello
world
since world Runnable starts after hello Runnable completes.