I'm just going through a Java course and several weeks before we went through multithreading where it was explained that when two(or more) threads work with the same object, the object has to be locked from all over threads except the one working with it.
Having a GUI I want to write some data from 2 threads to a JTextArea should I bother about locking the object when one thread writes to it or this is handled already by the JTextArea? If I should bother about it, how would I go doing this since I can not declare a Lock inside the JTextArea class definition? If I should not bother about this, does it stays the same with all swing object, if not, what are the exceptions?
For the most part, Swing is inherently not thread-safe, so you cannot do this - you must update all GUI components from the EDT by wrapping up the call in SwingUtilities.invokeLater(). For example:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.setText("Blah");
}
});
Although there are technically exceptions to this rule with a few select components, I'd still by far prefer to execute everything on the EDT unless there's a very good reason otherwise (very, very rarely the case.)
In Swing you have to update GUI components only from UI thread. So you have to schedule those updates from your threads to be executed on UI thread.
This is one example with SwingUtilities.invokeLater().
Related
When I start my GUI interfaces, what can happen if I don't use invokeLater?
Does that mean all rest of the GUI paints/updates/etc. will be in the main thread?
Will calling a repaint outside of an invokeLater make all subsequent calls fall into the main thread?
Basically this:
void main()
{
JFrame jmf();
setVisible(jmf);
}
------------- VS -------------
void main()
{
SwingUtilities.invokeLater(new Runnable(){
run(){
JFrame jmf();
setVisible(jmf);
}
}
});
NOTE: In cases with small GUI, I if I don't put the invokeLater it seems to work fine. And in fact the application doesn't terminate although the last line of the main is executed.
I have read quite a few articles on why we should use it pertaining to the fact that Swing is not thread safe (it is single threaded and so on), but I really didn't read the repercussions of not calling invokeLater (partially because of my limited knowledge in Threads)
The reality is, nothing might happen or the world will end. It's next to near impossible to predicate, this is the nature of multi-threaded environments...
Unless you are doing some really dynamic setups, until the a frame is made visible it "should" be okay not to do it within the context of the EDT.
The problem comes down to the fact that different platforms are implemented differently (at the native level). For example, the original requirement for using invokeLater when starting your UI seems to have come from deadlocks on the Sun OS many years back.
I've also seen some issues with Java 7 (but my predecessors idea of the thread was weird to say the least). The general advice is, use invokeLater to create and display your UI. Run all UI code within the context of the EDT
It will also reduce the risk of you having to spend weeks trying to replicate and track down those weird anomalies (by running you all you UI code from within the EDT)
Updated based on comments from the OP
repaint makes a request to the RepaintManager, that makes decisions about what and when something should be paint. It will actually post a "paint" event directly on to the Event Queue, which is then processed by the Event Dispatching Thread, so repaint is actually on (of the few) thread safe methods...
Take a look at
Painting in AWT and Swing
Initial Threads
Will the real Swing Single Threading Rule please stand up?
Why is Swing threading model considered wrong and how should it be?
The general advice would be, you should use invokeLater because that's how the API has been designed, doing anything else is inviting problems...
In my Java application with a Swing GUI, I would like to achieve the following.
There is a non-GUI thread running, performing some work. At one point, this thread needs input from the user before it can continue. Then, I would like to make some changes to the GUI, await a specific GUI action (like the user pressing the OK button), get the entered data from the GUI to the non-GUI thread, and let it continue with the computation.
Looking around, I have found a lot of information about how to initiate the execution of a (long running) task from the Swing GUI thread on another thread, but nothing on my problem.
SwingUtilites.invokeAndWait sounds like it does the job, but first, it takes a Runnable argument instead of a Callable, so there is no straightforward way to return a result, and second, it does not solve the problem of waiting for a certain GUI event.
I realize I could make up my own solution using e.g. a CountDownLatch, but to me, the problem seems frequent enough for there to be a standard solution.
So, my questions are: Is this really a frequent problem, and if yes, is there a solution in the standard library / libraries? If there is no standard solution, how would you solve it? If this problem doesn't occur often, why not?
Kicking off the GUI changes is easy, so I assume you're only asking about getting data back to the worker thread.
First, create a Blocking Queue. Have the worker thread call take() on the queue, and it will block. In GUI space, once the user enters valid input, put it on the queue with offer() and the worker thread will receive the data and can continue.
I think, you can use ExecutorService where you can also track progress of your task through Future interface.
java.awt.EventQueue.invokeLater works nicely for running code on the AWT EDT. Propbably best to copy mutable data or better use immutable data. Locks are possible, but a bit dicey.
If you other thread is an event dispatch loop, you could implement something like invokeLater for your thread (but don't make it static!). Probably use it behind some interface that makes sense to the behaviour of the thread - so it's real operations rather than run which is specified as doing anything it pleases. If your thread is going to block, then a BlockQueue is fine, but don't block from the AWT EDT.
java.awt.EventQueue.invokeAndWait is like using a lock. Probably you are going to use another lock. Or perhaps a lock like invokeAndWait on you own thread. If you don't, AWT uses a lock anyway. So, uncontrolled nested locks, that probably means deadlock. Don't use invokeAndWait!
final bool result = doSomething();
SwingUtilities.invokeLater( new Runnable(){
//Runnable method implementation.
//use result in your method like local var.
});
Make sure that your shared data is synchronized use lock objects.
If you need to pass arguments to Runnable just make your local variables final,
and use them in run method.
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 am trying to implement a GUI in java but I am beginner in swing. I want to make something clear. I read that in order to keep the GUI responsive I should use the SwingWorker class to do the task in a separate thread. Ok so far.
No I have a model with around 15 methods that are remote methods. Each method returns different object type as a result than the others.
In my view the user presses a button and the appropriate method in the model is called. Without using the swingworker the GUI froze. My question is, am I supposed to create 15 subclasses of Swingworker threads and create a NEW instance of each as needed according to user's actions? Is my understanding correct? Is there a standard way for this or what I say is a correct approach?
Thanks!
Have a look at this: Simple Background Tasks.
It seems you have two concerns. Firstly, regarding the amount of code required when using SwingWorker: you do need to create a subclass of SwingWorker for each action, but that doesn't mean they need to be top-level, named classes, or in their own files. They can be anonymous classes, as shown in the article, so that the code is within your GUI's event-handling code.
Secondly, regarding instantiation of SwingWorker objects: you can't reuse a SwingWorker, but since the jobs are being executed as a result of user activity (e.g. clicking a button), you shouldn't encounter any performance problems with instantiating new objects each time.
By all means, SwingWorkers get the job done. In my experience, I haven't liked using the SwingWorkers for just one little job. I prefer to spawn off a thread, and have that thread ask the EventDispatch thread to update the GUI. Only the EventDispatch thread should update the UI, though there are a few exceptions.
I would suggest reading about threads in threads in Swing.
Though threading can get heavy, and maybe this solution would not work for you in all cases, if a seperate thread needs to spark a change in GUI, use something like,
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run()
{
// this codes runs on the event dispatch thread
// update the ui here.
}
});