views:

191

answers:

4

I know what "thread" means and if I understand the event dispatching thread (EDT) as "just a thread", it explains a lot but, apparently, it does not explain everything.

I do not understand what is special about this thread. For example I do not understand why we should start a GUI in a the EDT? Why the "main" thread is bed for GUI? Well, if we just do not want to occupy the main thread why we cannot start GUI just in "another thread" why it should be some "special" thread called EDT?

Then I do not understand why we cannot start the EDT like any other thread? Why we should use some special tool (called invokeLater). And why GUI, unlike any other thread, does not start immediately. We should wait until it is ready to accept our job. Is it because EDT can, potentially execute several task simultaneously?

If you decide to answer this question, could you pleas use a really simple terminology because otherwise, I am afraid, I will not be able to understand the answer.

ADDED:

I always thought that we have one "task" per thread. So, in every thread we execute a predefined sequence of commands. But it seems to me that in the event dispatching thread we can have sever task. Well, they are not executed simultaneously (thread switches between different task but there are still several task in one thread). Is it right? For example there is one thread in the EDT which display the main window, and then additionally to that we sent to the EDT another task which should update one of the window components and EDT will execute this new task whenever it is ready. Is EDT differ from other threads in this way?

+2  A: 

What is the EDT?

It's a hacky workaround around the great many concurrency issues that the Swing API has ;)

Seriously, a lot of Swing components are not "thread safe" (some famous programmers went as far as calling Swing "thread hostile"). By having a unique thread where all updates are made to this thread-hostile components you're dodging a lot of potential concurrency issues. In addition to that, you're also guaranteed that it shall run the Runnable that you pass through it using invokeLater in a sequential order.

Note that it's not just that you're dodging the concurrency issue: you must respect Sun's guidelines regarding what must and what must not be done on the EDT or you'll have serious problems in your application.

Another benefit is that some Swing components tend to throw unwanted exceptions and when this happen they're automagically dealt with and won't crash the EDT (AFAIK if you really manage to kill the EDT it is automagically restarted).

In other words: you don't have to deal with all the broken Swing components and the exceptions they throw yourself: the EDT is taking care of that (just take a look at the countless Swing bugs throwing exceptions in Sun's bug parade, it's fascinating... And yet most apps keep working normally).

Also, by doing only what's mandatory in the EDT allows the GUI of your app to stay "responsive" even tough there may be tasks running in the background.

Webinator
+2  A: 

The important thing to remember is that Swing classes are not thread-safe. This means that you always should call Swing methods from the same thread, or you risk getting weird or undefined behavior.

So the solution: only call Swing methods from a single thread. This is the EDT thread - it's not special in any way other than that it is the thread designated to call swing methods from.

Now you may ask why are Swing methods not thread safe? After several unsuccessful attempts, GUI toolkit designers discovered that it's inherently impossible to design a thread-safe GUI toolkit. Too often events are passed in opposite directions (input events from bottom to top, application events from top to bottom) which always leads to deadlocks. So that's just the way it is.

amarillion
@amarillion: it is a bit special in that exceptions happening in the EDT are behaving differently than exceptions thrown in other threads and that should you kill the EDT it's automatically restarted.
Webinator
OK. This sounds to me as a practical solution. So, I put my GUI application in the EDT (using `invokeLater`) and then, if I have many other threads, and I want to call the GUI application from these thread, I just make these calls using `invokeLater` and everything should be fine. Does it work this way?
Roman
@Roman: exactly. But for a simple application, where you do all work in actionListeners and other event handlers, main() may actually be the only method that is not on the EDT. So you call invokeLater only once. Of course this is only true for simple applications, but it's enough to know for just getting started with java.
amarillion
+5  A: 

The event dispatching thread is the thread that handles all GUI events and manages your Swing GUI. It is started somewhere in the Swing code if you have any GUI in your program. The reason it is done behind the scenes is because of simplicity - you do not have to bother with starting and managing an extra thread by yourself.

Regarding the fact that you have to update your GUI with invokeLater() it is because of concurrency issues. The GUI can be modified only from one thread because Swing is not thread safe(it is worth to note that most of toolkits are not thread safe, there is a nice article that gives some ideas why). This is why you have to submit all GUI updates to run on EDT.

You can read more on concurrency in Swing and event dispatching thread in Sun tutorial on concurrency in Swing. Also, if you would like to see how this could be done in a different way you might like to check out SWT toolkit. In SWT you have to manage EDT by yourself.

pajton
+3  A: 

I always thought that we have one "task" per thread. So, in every thread we execute a predefined sequence of commands. But it seems to me that in the event dispatching thread we can have sever task. Well, they are not executed simultaneously (thread switches between different task but there are still several task in one thread). Is it right? For example there is one thread in the EDT which display the main window, and then additionally to that we sent to the EDT another task which should update one of the window components and EDT will execute this new task whenever it is ready. Is EDT differ from other threads in this way?

No, the EDT is not fundamentally different from other threads. And "task" is not a good word to use, because it could be confused with OS-level processes (which are also often called task). Better use Runnable, the interface used to give code to the EDT to execute via invokeLater().

The EDT is basically connected to a queue of things it has to do. When the user clicks a button on the GUI, a Runnable that notifies all listeners attached to the button goes into the queue. When a window is resized, a Runnable doing revalidate&repaint goes into the queue. And when you use invokeLater(), your Runnable goes into the queue.

The EDT simply runs an endless loop that says "take a Runnable from the queue (and if it's empty sleep until you're notified that it's not) and execute it.

Thus, it executes all those little Runnable pieces of code one after another, so that each of them basically has the GUI all to itself while it runs, and doesn't have to worry about synchronizing anything. When you manipulate the GUI from another thread, this assumption is broken, and you can end up with the GUI in a corrupted state.

Michael Borgwardt