I'm building a little software in Java, with a GUI.
I have an algorithm which runs continuously (Almost 24/7) (I have a stop/start button in GUI)
This algorithm should update a list and show a log on the GUI.
The question is- should I create a separate class or thread for this procedure (algorithm),
1) If the answer is yes - Should I transfer the GUI elements that I should update as parameters to that procedure? Would it cause problems updating the GUI?
2) If not - how should I design it?
Many thanks in advance!
You should use for heavy task SwingWorker, is designed for this situations. Here you have a nice article why do we need SwingWorker?.
You need this cause if your algorithm take for example 5 secs and you run in the same thread as gui, it's gonna to freeze your view until finish.
BTW all gui-components must be updated in the Event Dispatch Thread, so you don't have to update them in another thread cause they don't be updated.
The question is- should I create a separate class or thread for this
procedure (algorithm),
Yes, this is a common practice to do so.
Should I transfer the GUI elements that I should update as parameters
to that procedure? Would it cause problems updating the GUI?
You do not really required to pass anything. The only thing you need to enure is that all interactions with ui elements are done within ui thread (to avoid concurrency issues). Usually this is done by creating runnable that does ui-related job and passing it to UI framework you are using to be scheduled in ui thread.
Related
I'm building a game from the ground up in Java, using only standard libraries. So far I've got a game that prints ASCII characters in a swing window to represent 3d objects. It's pretty cool. Anyway, since I don't know about threading or scheduling, I'm wondering if I'm using some bad practices that could cause issues later on. I have one repeating task running to update the level every tenth of a second, but whenever I want to delay something, I use
Executors.newScheduledThreadPool(1).schedule... etc etc.
Is it good to make a "new scheduled thread pool" every time I want a new delayed task to run once, or should I try to keep one instance going? If it's good to reuse instances, when is it appropriate to make a new one?
Concurrency in Swing applications is tricky: everything that impacts the GUI needs to be executed on a single thread (called the event-dispatch thread). So when you set up a separate thread to perform some long-running background task (e.g. generating a map for an area the player isn't viewing yet) then you need to work carefully to synchronise with anything that might impact the GUI.
In general you have two options for the simpler use cases:
If it's a short activity that immediately impacts the GUI then use a Timer to trigger an event on the event-dispatch thread. See here.
If it's a long activity then use a SwingWorker. See here.
There are plenty of other ways to achieve interaction with other threads (e.g. see SwingUtilities.invokeLater and SwingUtilities.invokeAndWait) but given you have said you are just starting out I would suggest sticking to one of those two for now. They take care of most of the complexity for you and let you focus on your game logic.
Here is what I am trying to do:
I have a JFrame containing a JTextArea displaying updates on an on going connection. The user is supposed to be able to press the JButton to the right of it if they want to cancel the connection. However, since the connection is blocking (using) the thread while trying to connect, the GUI becomes frozen. I am looking for a quick fix. Having the ActionListener on a separate thread possibly? I do not have much experience with threads though I can make basic use of runnables.
Does the answer have something to do with using the EDT? If so how should this be implemented?
PS for clarification, the button should be able to kill a thread creating the connection. After reading it seems that an executorService. could help with this? Yes? or not at all?
It would be advisable to first get up to speed regarding Swing (or virtually any UI framework) and multi-threading. This is the napkin version:
Any modifications to the UI or reads from it (e. g. to get the value of a textfield) must be done only on the UI thread (which is also sometimes called the "Swing Thread" or "Event Dispatch Thread" (EDT)
Any blocking or long-running operations - like network communications - must NOT be run on the UI thread. Otherwise they will prevent buttons from working, texts from being updated etc.
In Java, the ExecutorService and its friends will make it relatively easy to let long-running or blocking stuff run on a background thread
If something happens on the background thread that requires you to update the UI, encapsulate the UI-related code in an EventQueue.invokeLater call. This will make sure the Runnable you pass gets executed on the UI thread.
The SwingWorker class encapsulates this logic and provides an easy to use helper for simpler cases.
When doing this the first time, it can be a bit daunting, but it pays off to understand this thoroughly, because it does not only apply to Swing, but to any other UI code, too.
for clarification, the button should be able to kill a thread creating the connection. After reading it seems that an executorService. could help with this? Yes? or not at all?
yes
while(localBooleanVariable) inside Runnable#Thread, plain Thread
by using SwingWorker.cancel()
easiest could be SwingWorker, because is cancelable and output from publish(), progress() is on EDT
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.
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.
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();
I have hundreds of different functions that run in the EDT. A great deal of them include long-running tasks and some include changes to the GUI. Occasionally the GUI hangs for users but it is hard to keep track of all the locations this happens due to the GUI hangs not happening in the same areas 100% of the time. The issue is not high priority because the hang usually starts working after a minimize/maximize of the window, but it needs to be done eventually.
After some research I discovered I could use doInBackground() under SwingWorker for any methods with labor-intesive work and use done() for GUI drawing. Also I believe I can use SwingUtilities.invokeLater for every GUI drawing that happens to be in the doInBackground() function. However, I want to avoid adjusting every one of the hundreds of functions in my code.
Is there a way I can use a single SwingWorker and send any long-running methods to the doInBackground() function? Using the invokeLater function multiple times for every misplaced GUI code where a SwingWorker would be used is not a problem as it is not that frequent.
If this is not possible is there some kind of alternative I can use? Thank you.
All methods that update the GUI must be invoked on the EDT, otherwise you may end up with some unexplained GUI behavior (which sounds like what you are seeing). You could have repaints that don't happen properly, thread races, etc.
It is not advised to run long running tasks on the GUI because they will cause the GUI to become unresponsive, so for long running tasks, SwingWorker is a good solution to use (note that the process and done methods are called on the EDT automatically so your worker can do its long running work in doInBackground but you can safely update the GUI without using SwingUtilities.invokeLater from the done method).
As you mentioned you have hundreds of methods and you don't want to call SwingUtilities.invokeLater every time, you might want to look into one of the task frameworks. The Swing Application Framework was developer under JSR-296 http://java.sun.com/developer/technicalArticles/javase/swingappfr/ but is not actively supported, but still provides a nice framework.
http://en.wikipedia.org/wiki/Swing_Application_Framework is a list of alternative frameworks.
It sounds like you are going to need to do some significant rewriting in your application. Calling GUI methods from outside the EDT is unsafe to do.
I don't see how what your asking would be possible. Swing has no way of knowing of what would qualify as a "long running" method call before execution. If the method is already being executed (on the EDT) Swing can't simply pick it up and move it to a new thread. Even if you would indicate which method calls should be run in background threads pulling it off would be hard. The only way I can think of to make this possible in Java is with AOP (you could intercept the method calls). But implementing AOP would be harder then reimplementing your existing application to use SwingWorkers.
It sounds like the architecture of your Swing application is broken. Long running tasks must not be executed on the EDT. I'm sorry but I think you just have to bite the bullet on this one. If you want your application to feel snappy, responsive and have predictable behavior you will have to fix this by putting the long running code in background threads.
If your application uses a lot of background tasks you might want to use the excellent Swing Task API. Otherwise you will find yourself in a SwingWorker spaghetti quite fast.
for every GUI drawing that happens to be in the doInBackground()
You can't call Swing drawing, updating, etc. methods in the 'doInBackground()' method (well actually you can, but you must not do that). This is because this is the method which gets executed off the EDT. GUI drawing and component updates must only be called in the 'done()' method of a SwingWorker.
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.
}
});