I have a heavy java project which does not work responsive to the users. I have found out that long time needed events in event dispatch thread can cause my project to work slowly. So, I have two question in this manner:
How can I monitor the event dispatch thread and see which events are in the queue and eventually, which ones spend more time in event dispatch thread? ( As you know invokeLater function insert the event to the end of the event dispatch queue. I want to monitor whole event dispatch queue)
How can I insert an event to the first of the event dispatch thread? (in this case, the GUI will be responsive).
Typically the slowness is caused by code that inadvertently tries to access the filesystem, network or database from the UI thread. Its usually pretty easy to fix with SwingWorkers once the cause has been identified.
Replace the Event Dispatch Queue with an implementation that monitors how long events in the queue take to process.
When an event takes too long the new queue implementation logs the stacktrace of the EDT.
If you are only used to looking at stacktraces when exceptions are thrown don't get alarmed. The new implementation isn't killing slow events or causing them to throw exceptions its just showing you what the EDT is doing at the moment when the unresponsiveness was detected.
Look at the printed stacktraces and figure out how to move the slow part of the event into another thread.
I believe Netbean's slowness detector implements something very similar.
You need to provide more details...but thread themselves don't have queues. You can not check to see what work is waiting on a thread, you can only check the status of any given thread (say in a thread pool).
If you have a concept of "work" that needs to be queued for eventually processing by a given "worker" (ie thread) you have to implement that yourself. Alternatively you can use a an actor system such AKKA which sounds like it would do what you require
Related
As far as I know, there are 3 threads in a Swing GUI application:
the main application thread, which executes the main() method
the toolkit thread, which receives the system events
the event dispatching thread, dedicated to the painting and event handling of the GUI stuff
Generally, the main method just makes a call to SwingUtilities#invokeLater(Runnable) in order to initialize a window and so on, thus the GUI initialization is made on the EDT... BTW, as far as I know (again), everything that touches the GUI must be executed on the EDT...
Questions: What is the main thread used / usable for? Does it just die after the call to invokeLater()? Does it consume resources? Can I (and is it a good practice to) use it to perform... I don't know... Network stuff?
A Swing programmer deals, actually, with 3 kinds of threads:
Initial threads (the one that executes the initial application code,
our main here)
The EDT (as you metioned)
Worker threads (to deal with background tasks)
The inital thread creates the Runnable to run swings tasks and schedule it in the EDT. After that, the program is primarly driven by the GUI, and the application code survives and can continue to execute other tasks (Network staff as you noticed) and consumes resources as much as it needs.
Any Swing component method must be invoqued by the EDT (but some of them) because they swing method are not "thread-safe". So,
SwingUtilities#invokeLater(Runnable)
just queues the runnable in the EDT task list and wait for its turn to run.
The doc here is quite helpful.
The main thread in a Java program dies when control reaches the end of main().
In the program architecture that you describe, the main thread already has created the EDT and maybe other threads by that point, and those other threads keep the JVM alive.
Every thread in Java is either a daemon thread, or a non-daemon thread. The latter is the default case for a new Thread. You have to call t.setDaemon(true) if you want a daemon.
A JVM will keep running as long as there is at least one non-daemon thread still alive.
What is the main thread used / usable for?
It is usable for any purpose that you would use any other thread for. It executes whatever code you write for it to execute.
I was comparing the differences between Swing's SwingWorker and Android's AsyncTask classes. While Android has a Main Thread/UI Thread and then spawns a background thread (using AsyncTask), SwingWorker has three threads that are involved -
Current thread
Worker thread
Event Dispatch Thread.
And then I also came across the statement (in docs) -
Often, the Current thread is the Event Dispatch Thread.
Now, what does this mean?
Does it mean that Swing also has only 1 thread - the Main Thread and
even the events are received on the same thread OR
Is it different for different JVM implementations?
This is only valid for Swing, which shares some similarities with Android UI programming but is indeed not the same.
A little bit of context
The EDT (Event Dispatch Thread) is Swing's thread dedicated to handling UI events (mouse and keyboard input, events on controls, rendering of the UI, etc...).
This is an Event Loop model, similar to what is done in Android.
The fact that event listeners in Swing are executed on the EDT is the root cause for freezing UIs in Swing applications: developers misunderstanding the threading model often put long-running code in the listeners, which blocks the EDT and thus the GUI.
SwingWorker was introduced to better guide developers in separating UI updates from long-running background code. It spawns a dedicated background thread for the I/O processing (or long-running task) in doInBackground and executes UI updates in done and process methods. While these 3 methods guarantee in which thread they'll be executed, all other methods are executed in the current thread.
What is meant by the sentence you quoted
The whole reason for SwingWorker to exist is to properly initiate a long-running process from the GUI, without blocking the GUI.
Often, it will be in reaction to a user's input (e.g. clicking a Button). Since reactions to the user's input (implemented as Listeners) are always executed in the EDT by the Swing framework, unless you happen to call execute or get from another thread explicitly, it will get executed on the EDT.
By the way, execute is "fire-and-forget" and is the typical use-case (call it from a listener). get on the other hand blocks, and is not suited to be called from a listener (it would defeat SwingWorker's purpose, call it on your own threads if needed)!
I have a program which should managing threads (create, interrupt and show working threads). And I need to notify main thread about finishing, interruption or exceptions in worker thread. Main thread should react on this events, and of course it should not be blocked. As I know it behavior released in android in handler class. But I have no idea, how it possible to do in java. Could someone help me with this problem?
If you have an event loop in your main thread, you can have a queue which it polls to see if any new events it needs to process are waiting. If you are using Swing or Android there will be an event loop already and a method you call to pass tasks to it.
I know the Swing single-thread rule (from Java Concurrency in Practice):
Swing components and models should be created, modified, and queried
only from the event-dispatching thread.
Is the converse also true? I maintain some transaction logging code that writes event information to a file and it sometimes does this on the EDT. Is this a bad practice?
That depends on what you are doing. Basically while you are using the EDT thread then it cannot do anything else. That means button clicks, processing, user interface updates, etc will all be stalled.
So for long-running tasks you should use a different thread (for example SwingWorker) but for anything that is unlikely to stall or take a long time doing it on the EDT is fine.
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?
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.
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.
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.
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.