After years of Java programming I always used to create my main() methods like this :
public static void main(String[] args)
{
runProgram();
}
But recently I studied some codes from the Web and saw this sometimes instead of the usual main() use above :
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
runProgram();
}
});
}
I simply want to know :
Why to use this instead of the usual main() way ? I can't see any difference when I give it a try.
What is the difference between these two ways ?
Thanks for reading me and your answers.
The docs explain why. From Initial Threads
Why does not the initial thread simply create the GUI itself? Because almost all code that creates or interacts with Swing components must run on the event dispatch thread.
and from The Event Dispatch Thread
Some Swing component methods are labelled "thread safe" in the API specification; these can be safely invoked from any thread. All other Swing component methods must be invoked from the event dispatch thread. Programs that ignore this rule may function correctly most of the time, but are subject to unpredictable errors that are difficult to reproduce.
Because the thread "main" started by VM is not the event dispatch thread.
A few Swing components from the API are not thread safe,which means that they may cause some problems like deadlock,So its better to create and update such swing components by using Event dispatcher thread provided by Swing but not from the main thread or any other thread created from main.
While the answers above are all correct, I believe they lack a correct explanation.
Yes, everything that interacts with Swing (creating the UI, updating it, adding new components or layouts, etc.) should be always done on the AWT event-dispatch thread (see this post for more information on the topic).
SwingUtilities.invokeLater() places your code in the FIFO Queue of the event-dispatch thread (EDT), so it will be executed from the EDT whenever it has finished the other tasks it was doing.
Having that said, the EDT should be used exclusively to run Swing-related tasks that are quick to perform (if you block the EDT, you block the whole UI).
There is no point using SwingUtilities.invokeLater() on the main method if you aren't using Swing/AWT (e.g. a JavaFX app or a terminal app).
If you want to perform some tasks that have nothing to do with Swing at all but they're required to start Swing (e.g. starting the Model and Controller in a MVC-like app), you could do it either from the EDT or the Main thread (see this post for a discussion on this topic).
Related
This question already has answers here:
What does SwingUtilities.invokeLater do? [duplicate]
(5 answers)
Closed 9 years ago.
When studying for an exam I stumbled upon some lines in java graphics that aren't really clear to me. So i started to glance and check some other programs and they were without those lines.
example:
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){//unknown
public void run(){ //lines
JPanel panel = new DrawingPanel();
...
}
now i know that Runnable and run have to deal with threads, but i don't know why and how do these two lines work
Swing objects can only be accessed from the Swing thread that runs in closed loop handling repaints, GUI events and so on. When you application starts, it starts in an ordinary thread (not a Swing thread). The lines that look strange to you use SwingUtilities to execute DrawingPanel constructor and probably more code in the Swing thread.
The code that instantiates the first GUI frame directly from the main thread may also work in practice if it is really the first method ever called (as expected). However it is "fundamentally wrong" approach that may not work later under different machine, if differently called and the like.
Swing is a single threaded framework. All interactions and updates with the UI are expected to be executed from within the context of the Event Dispatching Thread.
Java makes no guarenttees that main is executed within the EDT (I believe they normally call this the main thread). Therefore, you are required to ensure that any of your UI code is synced to the Event Dispatching Thread first.
SwingUtilities.invokeLater, delegates to EventQueue.invokeLater. This basically posts the Runnable instance into the event queue, which is processed by the Event Dispatching Thread.
At some time in the future, the Runnable is popped off the queue and the run method is executed within the EDT
See Initial Threads for more details
You could also look at The Single Thread Rule in Swing, Event-Dispatching Thread Rules for Swing UIs for additional info
I've read a few books about Java. In all of them there was at least one chapter teaching GUI programming. In all of them, creating a simple form application was following this logic:
MyFrame.java
public class MyFrame extends JFrame
{
JButton button1;
public MyFrame()
{
button1 = new JButton("Click here.");
}
}
FrameTest.java:
public class FrameTest
{
public static void main(String[] args)
{
MyFrame myFrame = new MyFrame();
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setSize(600, 600);
myFrame.setVisible(true);
}
}
Basically, just subclass JFrame to create a form and declare as instance variables the other components and initialize those components in the constructor. And then create another test class, instantiate the frame subclass in that class and call some of its methods to make it visible.
But in concurrency lessons I've learned that we have a main thread which runs main() in every application we create. As far as I know, when we use Swing in order to create GUI applications we have another thread (Event Dispatcher Thread). So if i am not mistaken, in every Swing based GUI application there are at least two threads. This makes every GUI application multithreaded. And in some articles and tutorials that I've read, it says that Swing doesn't support multithreading therefore all GUI components should be created and modified only in Event Dispatcher Thread otherwise Thread Interference and Memory Inconsistency Errors may arise.
Even in the simplest example in Wikipedia (http://en.wikipedia.org/wiki/Swing_%28Java%29), it's made like this via invokeLater method.
So which one is the true approach? Where am I wrong?
ALL interactions with any UI/Swing component MUST be done for within the context of the EDT
When starting an application, you should ensure that you are executing within the EDT BEFORE you try and create/interact with any Swing component.
Simply put, you should use something like...
EventQueue.invokeLater(new Runnable() {
public void run() {
// Now in the event dispatching thread
}
});
If you need to run long running task or perform any blocking task, you should execute it in a separate thread. SwingWorker is a good choice in most cases as it provides some simple mechanisms for re-syncing code to the event dispatching thread.
Take a read through
Initial Thread
Will the real Swing Single Threading Rule please stand up?
So, the short answer is, yes, all Swing based code should be accessed/modified/interacted with from the context of the EDT
So if i am not mistaken, in every Swing based GUI application there
are at least two threads
Yes. One is main thread and other is EDT(Event Dispatch Thread).
This makes every GUI application multithreaded.
Yes. But in that case , the other thread is not interacting with the GUI component.
Swing doesn't support multithreading therefore all GUI components
should be created and modified only in Event Dispatcher Thread
otherwise Thread Interference and Memory Inconsistency Errors may
arise.
Yes , Absolutely true. This means that at a time only one Thread should interact with the given GUI component.
A Swing programmer deals with the following kinds of threads:
Initial threads, the threads that execute initial application code.
The event dispatch thread, where all event-handling code is executed. Most code that interacts with the Swing framework must also execute on this thread.
Worker threads, also known as background threads, where time-consuming background tasks are executed.
The programmer does not need to provide code that explicitly creates
these threads: they are provided by the runtime or the Swing
framework. The programmer's job is to utilize these threads to create
a responsive, maintainable Swing program.
I read somewhere that for any thread that affects the visuals of the gui it should be ran in the EDT using SwingUtilities.invokeAndWait/invokeLater
For a basic gui, is it necessary to put something like new SwingGUI().setVisible(true); in the line of the EDT using invokeAndWait? Just to display?
Does this count?
The short answer to your question is: yes, even calling setVisible should happen on the EDT. To find out whether the current thread is the EDT, you can use the EventQueue#isDispatchThread method
Some reference links:
Multithreaded Swing Applications
Threads and Swing
Concurrency in Swing
Edit:
after reading the links I provided, it seems some of the articles on the Oracle site are outdated as in they still document you can create Swing components on another thread. There is a stackoverflow question on this which contains some nice answers and links to blogposts and articles about the 'new' policy (new as in a few years old)
Yes, if you touch a Swing object you have to do it on the EDT. In most cases you are already there, but if not, use the SwingUtilities classes. The reason for this is that the Swing classes are not multi-threaded, so you are likely to cause nasty problems if you access it on other threads. And it could be that setVisible() is doing a lot of things under the covers to make something display (like re-laying things out). Better to be safe.
Anything that is called from your
public static void main(String[] agrs) {
directly (without spawning another thread or using invokeLater) is running on the main thread.
Accessing GUI objects with the main thread while they may be being accessed (simultaneously) by the EDT (which is triggered by user input) can cause threading issues. Calling invokeLater causes tasks (runnables) to run on the EDT, preventing simultaneous access by other EDT tasks ie. button presses etc.
If you can be sure the EDT is not busy (before the first window is setVisible(true)) you can access the GUI from the main thread. If you can be sure the EDT has no reference to the component you're working on (it is out of EDT's scope) ie. before it's added to any container, you can access it from main thread without the EDT accessing it simultaneously, as the EDT has no way to reach it.
Everything that access Swing objects should do so via the Event Dispatch Thread (EDT). There is one small exception to this (which I'll mention later). The purpose of the EDT is to process any events that may occur due to IO (mouse and keyboard events). Quite a lot of the time this can mean altering the layout of your GUI. Swing was not developed to be thread-safe, meaning that that if two thread try to modify the same component at the same time then you can end up with a corrupted GUI. Since there is already one known thread to be accessing Swing components (the EDT), no other thread should attempt to modify them or even read their state.
Now, to the exceptional case when you can manipulate Swing objects outside of the EDT. Before any components have become visible it is not possible for IO to be triggering events. Therefore, the main thread can setup a Swing GUI and then set a single JFrame to be visible. Since there is now a visible frame IO events can occur and the main thread should not try to modify any more Swing components. The should only use this option to get a GUI started, and really only with toy problems.
What I'm saying is that the following is fine and won't cause problems if you're just playing around with stuff.
public static void main(String[] args) {
// create components
JFrame f = new JFrame();
...
// do layout and other bits of setup
// show gui to user
f.setVisible(true);
}
I learned about how swing isn't thread-safe. Delving deeper, I discovered that every modification to a swing component must be done on the Event Dispatch Thread in order to prevent various issues associated with multithreading. However, the information seemed to completely stop there. There doesn't seem to be a good tutorial that explains how to do this anywhere accessible on the internet.
Patching together information from code posted in relation to other issues, it seemed that I would have to put an untidy block of code around every single swing modification in my program (like this example from my own code):
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
setTitle("Frame title");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(800, 480);
setLocationRelativeTo(null);
setIconImage(Toolkit.getDefaultToolkit().createImage(ClassLoader.getSystemResource("Frame icon.png")));
}
});
} catch (Exception e) {
e.printStackTrace();
}
Basically, is this right? Do I have to put that code (or the equivalent with invokeLater) around every modification to a Swing component in my code?
Also, why doesn't Swing do this automatically?
The trick is that when swing calls you it will ALWAYS be in the EDT, so you don't have to worry about it.
However if you are in a timer or an action triggered by some other external event, your main thread or any other thread you've created then yes, you have to use invokeLater or invokeAndWait.
In other words, yes swing does do "it" automatically. Needing to use invokeXx is so rare that if swing were to do it internally it would waste too much time.
Many java programmers never figure this out and it can cause some pretty nasty hard-to-find problems with drawing your GUI. I do wish swing threw an exception when you called it not using the EDT--Java would have a better reputation when it came to professional GUIs if it did because there would be less crap out there.
note that any code executed from event handlers is already run in the EDT (the Event in the acronym)
this means that for general use (while you don't mess with swingworkers and threadpools and such) you are always inside the EDT
and you can always query if you are in the EDT with SwingUtilities.isEventDispatchThread()
also note that in your code the call to invokeAndWait will fail and throw an error when you are in the EDT already
Basically, you dont draw or update the GUI from outside of the EDT.
You use SwingUtilitis.invokeLater() from another thread to ensure the GUI drawing or updating code is run on the EDT.
Not all your UI code must be part of a runnable in an invokeLater call. That is simply because a large part of your program will be run on the EDT anyway. You need to dispatch messages to the EDT only when you are on a different thread.
I'm developing a small app, which would have Swing GUI. App is doing IO task in another thread, when that thread finishes GUI should be updated acordingly to reflect thread's operation result. Class running in a (worker, non-GUI) has object passed to it in contructor which would be used for updating GUI, so I don't need to put GUI stuff in a non-GUI class, but rather pass object for updating GUI to that class.
As I understand form reading here, (thread/swing) safe options for updating (changing) Swing GUI would be to use javax.swing.SwingUtilities.invokeLater(), javax.swing.SwingUtilities.invokeLaterWait() and/or javax.swing.SwingWorker() which basically are doing the same thing.
This all threading issue with Swing is a little confusing for me, and yet I need to use threads to do anything meaningful in GUI apps and not hung GUI while processing in EDT, so what interests me for now is this:
Are invokeLater and invokeLaterWait like sending message to EDT and waiting for it do it when it finishes processing messages that were before that call?
is it correct from Swing thread safety aspect, to do something like this:
interface IUPDATEGUI {
public void update();
}
// in EDT/where I can access components directly
class UpdateJList implements IUPDATEGUI {
public void update() {
// update JList...
someJList.revalidate();
someJList.repain();
}
}
class FileOperations implements Runnable {
private IUPDATEGUI upObj;
List<File> result = new ArrayList<File>; // upObject is accessing this
public void FileOperations(IUPDATEGUI upObj) {
this.upObj = upObj;
}
private void someIOTask() {
// ...
// IO processing finished, result is in "result"
}
public void run() {
someIOTask();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
upObj.update(); // access result and update JList
}
}; );
}
}
In case this isn't correct then how should this be done?
If I could, I would prefer to use invokeLater instead of SwingWorker if possible, because I wouldn't need to change my whole class and it's somehow more neat/distinct me (like sending a message in Win32 apps).
Thanks in advance.
Using invokeLater() and invokeAndWait() passes the Runnable parameter into the queue awaiting execution in the EDT. So calling invokeLater() will cause the Runnable to execute in the EDT when the EDT is able to process the request. invokeAndWait() simply waits (in the calling thread) until this execution takes place.
Using SwingWorker is ideal if you want to do background tasks that notify the EDT either at the end of execution or in intermediate states. An example would be to pass the current progress of a process to a JProgressBar.
For your example it seems that SwingWorker is a better choice but if you don't want to change your code too much then calling invokeLater() when the process is done will be just fine.
I'd recommend not using the invokeAndWait until java 7. I found a spurious wake-up on this method that can cause really painful bugs. For me it led to some really rare and hard to debug null pointer exceptions.
http://bugs.sun.com/view_bug.do?bug_id=6852111
It's fixed as of java 7 b77.
invokeLater is fine. This puts the call into the AWT event queue, so that it will get executed in the EDT in due course. Your program will continue running, and does not wait for your callable to get called.