Java Event-Dispatching Thread explanation
Asked Answered
G

2

69

I've recently started learning and exploring the basics of GUI programming in Java.

Having been programming for a while I have only done backend work or work and as a result the closest I've gotten to user interfaces is the command console (embarrassing I know).

I'm using Swing and as far as I can gather that means by extension I am also using AWT.

My question is based on this piece of code:

java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
        new frame.setVisible(true);
    }
} );

I have been researching this for a while as I wanted to fully understand this strange piece of code and have come across the term 'Event-Dispatching Thread' multiple times. Correct me if I'm wrong but as I understand it; it has to do with using multiple threads and how Java Swing interprets those threads. I gather as well that the above code is used to make sure all the threads are 'safe' before it creates the window, hence the invokeLater?

I have read that:

"You can only call methods that operate on the frame from the Event-Dispatching Thread"

and that only under certain circumstances can you call methods that operate on the frame from the main method.

Can somebody please clarify to me what exactly the Event-Dispatching Thread is?

How it relates to multiple threads of execution and how those threads are not safe to be called from the main method? Also why do we need this invokeLater?

Can we not just create the window as any other object?

I've hit a bit of a road block in my research as I'm not grasping these relations and ideas.

A side note is that I like to base my knowledge on in-depth understanding as I believe this leads to the best overall outcome and as a result the best programs. If I understand in-depth how something works then you can use the tips and tweaks effectively rather than just parroting them back in to code, so please don't be afraid to give me some extra in-depth explanations and broaden my knowledge.

Thank you.

Gerkman answered 27/8, 2011 at 20:1 Comment(0)
F
79

The event dispatch thread is a special thread that is managed by AWT. Basically, it is a thread that runs in an infinite loop, processing events.

The java.awt.EventQueue.invokeLater and javax.swing.SwingUtilities.invokeLater methods are a way to provide code that will run on the event queue. Writing a UI framework that is safe in a multithreading environment is very difficult so the AWT authors decided that they would only allow operations on GUI objects to occur on a single special thread. All event handlers will execute on this thread and all code that modifies the GUI should also operate on this thread.

Now AWT does not usually check that you are not issuing GUI commands from another thread (The WPF framework for C# does do this), meaning it's possible to write a lot of code and be pretty much agnostic to this and not run into any problems. But this can lead to undefined behavior, so the best thing to do, is to always ensure that GUI code runs on the event dispatch thread. invokeLater provides a mechanism to do this.

A classic example is that you need to run a long running operation like downloading a file. So you launch a thread to perform this action then, when it is completed, you use invokeLater to update the UI. If you didn't use invokeLater and instead you just updated the UI directly, you might have a race condition and undefined behavior could occur.

Wikipedia has more information

Also, if you are curious why the AWT authors don't just make the toolkit multithreaded, here is a good article.

Fireball answered 27/8, 2011 at 20:39 Comment(11)
My apologies for the late reply, I've been kept up with work. Your post has actually quite concisely answered an awful lot of my questions, so I'd like to thank you for that. Okay, so if I understand correctly then in order to operate on the GUI I should use the invokeLater() method with a runnable object and by doing this I can ensure I am always using the EDT? I also read about the SwingWorker class that is now officially supported. Would this class be considered to be superior to the invokeLater method or am I misunderstanding and they solve two different problems?Gerkman
There are a number of cases where you are guaranteed to already be executing on the EDT for example event handlers (ActionListeners, ClickListeners) so there is no need to use invokeLater from there. I think a SwingWorker is just a thread that has special mechanism to interact with the EDT (probably through invokeLater). So i would definitely use that if appropriate.Fireball
Okay, that makes sense, thanks a lot. You've cleared up quite a few discrepancies for me.Gerkman
"Runs in an infinite loop processing event" in the sense, does it use polling?Machismo
@Machismo it uses a standard multithreaded queueing approach using wait/notify to signal when new events arrive. This way it can avoid expensive polling, see: grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…Fireball
That means the thread sleeps when their is no event to process and wakes up when it gets a native event. Am i right? Thank you.Machismo
@Machismo well it waits until it gets a signal, signaling happens when an event is placed on the queue. One of the things that puts items on the queue is a native event, but things like invokeLater will put things on the queue also.Fireball
Also is it the same in case of awt too?Machismo
@Machismo we are only talking about AWT? Swing is built on top of AWT and ultimately delegates to the same core event dispatching system. I would suggest that you read up on some AWT basics since you appear to be confused about some of the terminology.Fireball
Event dispatch thread is there for AWT too. I understand, thank you. There is one doubt, is AWT thread-safe? (I think it is).Machismo
Hi, the link to the Java blog post no longer leads to a blog post. Can you update your link, or post a link to some archived version of that post?Argue
A
14

EventDispatchThread (EDT) is special thread reserved only for Swing GUI and *Swing's related events e.g. create/change/update Swing JComponents, more for asked questions here and here

all output to the GUI from BackGround Tasks, Runnable#Thread must be wrapped into invokeLater(), from synchronized Objects into invokeAndWait();

Adiell answered 27/8, 2011 at 20:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.