What is the rationale of SwingWorker? - java

For what I can read, it is used to dispatch a new thread in a swing app to perform some "background" work, but what's the benefit from using this rather than a "normal" thread?
Is not the same using a new Thread and when it finish invoke some GUI method using SwingUtilities.invokeLater?...
What am I missing here?
http://en.wikipedia.org/wiki/SwingWorker
http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html

Yes, you can accomplish what a SwingWorker does with vanilla threads + invokeLater. SwingWorker provides a predictable, integrated way to accomplish tasks on a background thread and report result on the EDT. SwingWorker additionally adds support for intermediate results. Again, you can do all of this yourself but sometimes it's easy to use the integrated and predictable solution especially when it comes to concurrency.

A code example:
import org.jdesktop.swingx.util.SwingWorker; // This one is from swingx
// another one is built in
// since JDK 1.6 AFAIK?
public class SwingWorkerTest {
public static void main( String[] args ) {
/**
* First method
*/
new Thread() {
public void run() {
/** Do work that would freeze GUI here */
final Object result = new Object();
java.awt.EventQueue.invokeLater( new Runnable() {
public void run() {
/** Update GUI here */
}
} );
}
}.start();
/**
* Second method
*/
new SwingWorker< Object , Object >() {
protected Object doInBackground() throws Exception {
/** Do work that would freeze GUI here */
return null;
}
protected void done() {
try {
Object result = get();
/** Update GUI here */
}
catch ( Exception ex ) {
ex.printStackTrace();
if ( ex instanceof java.lang.InterruptedException )
return;
}
}
}.execute();
}
}
The choice always depends on personal preference and use case.
The second method has an advantage when refactoring. You can more easily convert the anonymous class to an inner class when the method it's used in is too large.
My personal preference goes to the second, for we have built a framework where SwingWorkers can be added and are executed one after the other...

SwingWorker is an implementation of a common pattern (in .Net i read there is GuiWorker BackgroundWorker for this), where you have to do some work in a GUI program, but keep the GUI responsive. The problem is that often GUI libraries are not multi thread safe, so the common way to implement such workers is to use the message loop of the library to transfer messages into the event loop of the application.
These classes allow you to easily update your GUI. Usually, they have a update(int status) method that is called by the thread, dispatched by the class, and handled by the GUI, while the thread continues its work.
Using normal threads, you would need to code your own events or some other messaging mechanism for this task, which can be a pain if you need this functionality often. Using invokeLater in Java for example, you would intermix the code for updating the gui into the code for doing the work. The SwingWorker allows you to keep things separate.

to answer your question, you are not missing anything. this class is just a convenient utility for wrapping up the functionality you discribed (start another thread to do the background work and then invoking some final action on the EDT with the results).

When working with Swing, it is important to know that the main swing processing (ie. rendering) happens on a single thread (which is not your main thread). This is often called the Swing or awt event thread. Those familiar with the JDK pre 1.6 will remember the "grey rectangle" bug if you spent too much time in an event dispatcher for a swing component. What does this mean. In any swing application you will have 2 threads running that you will now have to deal with. Normally if all your operations within an event dispatcher (the code that gets fired say when a button is clicked) is short (ie. changing the state of a siwng button) you can just run this inside of the event dispatcher. If your application is going to call a web service or a database, or you application state is driven by external events (ie. jms) or you want to just make your UI more interactive (ie. build a list of items and be able to do something else) you should use a thread other than the awt event thread (the main swing one). So in these cases you spawn a new thread and do what you have to, and when the results finally come back, you then somehow have to create an event that can be executed by the awt/swing dispatcher. SwingWorker is a great little design pattern that allows you do to do this (the other way is SwingUtilities). It is particularly useful for doing fetch data from external sources or say long calculations (rendering a graphics scene). It helps automate the dispatch and subsequent re-integration of the results from an external thread (other than the awt thread). For async events (ie. an event from JMS needs to update a result, use SwingUtilities).

SwingWorker makes trivial example code much more concise. However it creates a ball of mud. Communications to and from the GUI and executed logic are all welded together. So, I'd not like to see it used in real production code.

SwingWorker is far easier than mucking with your own threads because it gives you two things that are painful to manually, thread coordination between the UI and the background process and doing loops effective, background work that keeps working and sending updates back to the UI incrementally, like process a large amount of data, or loading a large list. The disadvantage (or advantage) depends on how you look at it, is that it hides the underlying implementation, so future version may have different behavior, performance, etc, which may be undesirable. I've found it quite useful as the glue between a UI event and my own command code, the SwingWorker maintains the link to the UI and my code pumps data.

Related

How to properly implement a glass pane in Java?

I'm attempting to add a fancy InfiniteProgressPanel as a GlassPane for my big Swing program. However, it does not appear. It looks similar to this:
...
InfiniteProgressPanel glassPane = new InfiniteProgressPanel();
setGlassPane(glassPane);
...
glassPane.start();
doSomeStuff();
glassPane.stop();
...
I believe it is running in the same thread as the long process it is meant to cover up. I'll admit, I don't know nearly enough about threads, and I should probably figure out how to run that InfiniteProgressPanel GlassPane in a separate thread, and the long process in its own thread, too.
Be sure to:
Run all long running code in a background thread. This is a must.
Sounds great! How do I do so? Encapsulate all of the long-running code inside of an .invokeLater method? And should that be SwingUtilities.invokeLater or EventQueue.invokeLater? And what's the difference, anyway?
No, by using SwingUtilities.invokeLater(new MyRunnable) you're doing exactly the opposite -- you're guaranteeing that the long-running code will be called on the Swing event thread -- the exact opposite of what you want. Instead use a SwingWorker's doInBackground() method to run the long-running code. Regarding your second point, there's no difference whatsoever between SwingUtilities.invokeLater and EventQueue.invokeLater.
Make most all Swing calls on the Swing event thread, also a must.
Fantastic! Again, how do I do so? Same thing as above?
By using SwingUtilities.invokeLater(new MyRunnable) as noted above, or if you're using a SwingWorker then use its publish/process method pair as the SwingWorker tutorial will show you.
Call setVisible(true) on your glass pane since per the JRootPane API, all glasspanes are by default invisible.
Romain Guy's InfiniteProgressPanel doesn't seem to need a setVisible(true). It appears when the InfiniteProgressPanel.start() method is called.
I am not familiar with this, do you have a link?
Threads are different processes in the same program, per se.
In java, there are many different thread types, and the one you need for this job is SwingWorker.
The definition/use of this, from Oracle's docs, is:
When a Swing program needs to execute a long-running task, it usually uses one of the worker threads, also known as the background threads. Each task running on a worker thread is represented by an instance of javax.swing.SwingWorker. SwingWorker itself is an abstract class; you must define a subclass in order to create a SwingWorker object; anonymous inner classes are often useful for creating very simple SwingWorker objects.
As you can see, this is what you need; a background thread.
final InfiniteProgressPanel glassPane;
...
class GlassPaneHandler extends SwingWorker<String, Object> {
#Override
public String doInBackground() {
glassPane.start();
return setUpPaneAndStuff();
}
#Override
protected void done() {
try {
glassPane.stop();
} catch (Exception e) { } //ignore
}
private void setUpPaneAndStuff() {
//code
}
}
...
(new GlassPaneHandler()).execute(); //place this in your code where you want to initiate the pane
for more see:http://docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html
When you are updating a swing UI you need to do it in Swing's Event Thread. This includes creation of components or any sort of progress updates. You can do this via the SwingUtilities.invokeLater(Runnable) method.
Therefore, you should create the glasspane and show it via the invokeLater if in a background thread. Any progress updates to the glasspane from your long running process thread should be done via the invokeLater.

JavaFX 2: background and Platform.runLater vs Task/Service

I'm pretty confused about the concept of Task/Service in JavaFX.
I have used a model based on a background thread for my background work, which call Platform.runLater for any update to the UI.
Let's say I'm not interested in a progress bar or such. I'm doing some real work on my model that must be updated in the view of the GUI (e.g a list of participants which updates over time based on some connection in the background, list of participant based on some user input, classified by age and origin). This is what I usually achieve with background threads that I start, and within which I use Platform.runLater.
Now in JavaFX 2 they have all this concurrency using Tasks and Services, suggesting that it is better to use them. But I don't see any examples that achieve what I'm talking about.
Updating the progress bar by binding some properties is nice (but those are information on the task not your model).
So, how can I actually update the content of my views based on my model? Should I call Platform.runLater from within the Task? If not, what is the mechanism? How do I catch when the tasks have succeed and get the result (the update of the actual model) to update the view?
The tutorials by Oracle unfortunately were not very good in this regard. Pointing me to some good tutorials would also help.
The Task and Service classes are designed to encourage good practice and proper use of concurrency for some (but not all) common scenarios in GUI programming.
A typical scenario is that the application needs to execute some logic in response to a user action which may take a long time (maybe a long calculation, or, more commonly, a database lookup). The process will return a result which is then used to update the UI. As you know, the long-running process needs to be executed on a background thread to keep the UI responsive, and the update to the UI must be executed on the FX Application Thread.
The Task class provides an abstraction for this kind of functionality, and represents a "one-off" task that is executed and produces a result. The call() method will be executed on the background thread, and is designed to return the result of the process, and there are event listeners for when the task completes that are notified on the FX Application thread. The developer is strongly encouraged to initialize the Task implementation with immutable state and have the call() method return an immutable object, which guarantees proper synchronization between the background thread and the FX Application Thread.
There are additional common requirements on these kinds of tasks, such as updating a message or the progress as the task progresses. The application may also need to monitor the life-cycle state of the class (waiting to run, running, completed, failed with an exception, etc). Programming this correctly is quite subtly difficult, as it necessarily involves accessing mutable state in two different threads, and there are many application developers who are unaware of the subtleties. The Task class provides simple hooks for this kind of functionality and takes care of all the synchronization.
To use this functionality, just create a Task whose call() method returns the result of your computation, register a handler for when the state transitions from RUNNING to SUCCEEDED, and run the task in a background thread:
final Task<MyDataType> task = new Task<MyDataType>() {
#Override
public MyDataType call() throws Exception {
// do work here...
return result ;
}
};
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
MyDataType result = task.getValue(); // result of computation
// update UI with result
}
});
Thread t = new Thread(task);
t.setDaemon(true); // thread will not prevent application shutdown
t.start();
The way this works behind the scenes is that the Task maintains a state property, which is implemented using a regular JavaFX ObjectProperty. The Task itself is wrapped in a private implementation of Callable, and the Callable implementation is the object passed to the superclass constructor. Consequently, the Callable's call() method is actually the method executed in the background thread. The Callable's call() method is implemented as follows:
Schedule a call on the FX Application thread (i.e. using Platform.runLater()) that updates the state, first to SCHEDULED, then to RUNNING
Invoke the call() method of the Task (i.e. the user-developed call() method)
Schedule a call on the FX Application Thread that updates the value property to the result of the call() method
Schedule a call on the FX Application Thread that updates the state property to SUCCEEDED
This last step will of course invoke listeners registered with the state property, and since the state change was invoked on the FX Application Thread, so to will those listeners' handle() methods.
For a full understanding of how this works, see the source code.
Commonly, the application may want to execute these tasks multiple discrete times, and monitor the current state representing all of the processes (i.e. "running" now means one instance is running, etc). The Service class simply provides a wrapper for this via a createTask() method. When the Service is started, it gets a Task instance by calling createTask(), executes it via its Executor, and transitions its own state accordingly.
There are of course many concurrency use cases that don't fit (at least cleanly) into the Task or Service implementations. If you have a single background Thread that is running for the entire duration of your application (so it represents a continuous process, rather than a one-off task), then the Task class is not a good fit. Examples of this might include a game loop, or (perhaps) polling. In these cases you may well be better off using your own Thread with Platform.runLater() to update the UI, but of course you have to handle proper synchronization of any variables that may be accessed by both threads. In my experience, it is worth spending some time thinking about whether these requirements can be re-organized into something that does fit into the Task or Service model, as if this can be done the resulting code structure is often much cleaner and easier to manage. There are certainly cases where this is not the case, however, in which case using a Thread and Platform.runLater() is appropriate.
One last comment on polling (or any other requirement for a periodically-scheduled background task). The Service class looks like a good candidate for this, but it turns out to be quite hard to manage the periodicity effectively. JavaFX 8 introduced a ScheduledService class which takes care of this functionality quite nicely, and also adds handling for cases such as repeated failure of the background task.

java custom event on event dispatch thread

I am building a java application and i have implemented custom listeners and events. The problem now is that there are many events and listeners and the application GUI thread is being blocked while the listeners process the events. Can this be solved using event dispatch thread? If so how?
The code for listeners:
public class ProjectChangeObserver
{
private List<ProjectChangeListener> listeners = new ArrayList<ProjectChangeListener>();
public void addProjectChangeListener(ProjectChangeListener l)
{
listeners.add(l);
}
public void removeProjectChangeListener(ProjectChangeListener l)
{
listeners.remove(l);
}
public void removeAllProjectChangeListeners()
{
listeners.clear();
}
public void fireProjectChange(ProjectChangeEvent e)
{
if(listeners.size() > 0)
{
ArrayList<ProjectChangeListener> safeCopy = new ArrayList<ProjectChangeListener>(listeners);
for (ProjectChangeListener cl : safeCopy ) {
cl.onProjectChange(e);
}
}
}
}
One of the features of Swing is that it is single-threaded.
However, there is nothing stopping you from spawning your own threads to do background processing. As long as you only make calls to revalidate() or repaint() then all the drawing will still be handled in the Swing thread.
(Remember that if you are going to be spawning other threads to do background work then ensure that your variables are declared volatile if you expect the Swing thread to see the same values as in your threads. Or pass the information back through another listener.)
If you are intending to do the painting itself (e.g. of custom components) in separate threads, then it is either not possible or very strongly discouraged depending on the situation. (Some exotic situations may permit multi-CPU generation of a scene in a custom thread-safe buffering class, but you're unlikely to be doing that).
If you are finding that your Listeners are CPU/network intensive, then you might want to think about the architecture of who is doing the majority of the shouting and who is doing the listening. I always try to minimise the amount of shouting in my "view" code so that it simply responds to events.
Incidentally, I've found Project Lombok and its Beta sister Lombok PG to greatly reduce the boilerplate of implementing the Listener pattern with #ListenerSupport.
Quite to the contrary, this must be solved avoiding the Event Dispatch Thread ("GUI thread" is just another name for the same thing). You must use SwingWorker to start an asynchronous task in its own thread.
You should run separate threads for your events if you want to prevent UI blocking.
If you want to use a single thread for events then you can create the thread and you can pass commands to your event thread using a queue where you store your events.
But you should open async threads for your events if possible and you should make sure you refresh the UI whenever needed.

Changing Color of a Java graphic object

I'm trying to flash a Java graphic object by changing the color and calling the repaint() method. The color is only updating with the final change color call. Here is my code:
public void start() {
try {
Color origColor = node.getColor();
for (int i=0; i<noOfFlashes; i++) {
Manager.gui.getDrawGraph().changeNodeColor(node, Color.WHITE);
Thread.sleep(500);
Manager.gui.getDrawGraph().changeNodeColor(node, origColor);
Thread.sleep(500);
}
Manager.gui.getDrawGraph().changeNodeColor(node, Graph.VISITED_NODE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
and the change node color method is:
public void changeNodeColor(Node node, Color c) {
node.setColor(c);
repaint();
}
The change node color is in the same class as the paint component.
Any help would be much appreciated.
You need to use separate thread to manage your GUI event.
You can do this, using a SwingWorker, as suggested by Amine, or implement the Runnable interface, or extend the Thread class, developing the run() method, that is the task of your thread.
You can read this old question of SO : How do I use SwingWorker in Java?
A tutorial for SwingWorker : http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
A tutorial to make a Thread : http://docs.oracle.com/javase/tutorial/essential/concurrency/
The color is only updating with the final change color call.
If you don't use a separate thread, your gui will freezing until the method is completely executed, and you won't see the color change separated by Thread.sleep(500);.
UPDATE
In this link, in the paragraph Why does a Swing GUI freeze or lock up?, you can understand why a Java Swing GUI freezes, with the use of a single thread.
Check also this official link, in the paragraph Creating Threads, and this page, that returns:
Swing's single-thread rule says that Swing components can only be
accessed by a single thread. This rule applies to both gets and sets,
and the single thread is known as the event-dispatch thread.
The single-thread rule is a good match for UI components because they
tend to be used in a single-threaded way anyway, with most actions
being initiated by the user. Furthermore, building thread safe
components is difficult and tedious: it's a good thing not to be doing
if it can be avoided. But for all its benefits, the single-thread rule
has far-reaching implications.
Swing components will generally not comply with the single-thread rule
unless all their events are sent and received on the event-dispatch
thread. For example, property-change events should be sent on the
event-dispatch thread, and model-change events should be received on
the event-dispatch thread.
For model-based components such as JTable and JTree, the single-thread
rule implies that the model itself can only be accessed by the
event-dispatch thread. For this reason, the model's methods must
execute quickly and should never block, or the entire user interface
will be unresponsive.
I think that the sentences above are very useful to understand better the Swing package.
I report the suggestion of trashgod.
You can use the Timer class, from the javax.swing.Timer package. That is also a good alternative.
In this question, trashgod reports some examples of Timer.
Check here for a tutorial about Timer.
Based on what i understand from your code, I will probably recommend the use of SwingWorker.
I know you do not have any cost expensive code but you using SwingWorker, you will be able to update your GUI more easily.
I am not sure which framework you're using here... but you may need a repaint() just before the Thread.sleep(). Is there a Manager.gui.repaint() perhaps? (Sorry, complete guesswork here...)

Prevent Swing GUI locking up during a background task

I have a swing application which stores a list of objects. When the users clicks a button,
I want to perform two operations on each object in the list, and then once that is complete, graph the results in a JPanel. I've been trying SwingWorker, Callable & Runnable to do the processing, but no matter what I do, while processing the list (which can take up to a few minutes, as it is IO bound), the GUI is locked up.
I have a feeling it's probably the way I'm calling the threads or something, or could it be to do with the graphing function? That isn't threaded as it is very quick.
I have to do the two processing stages in order too, so what is the best way to ensure the second one has waited on the first? I've used join(), and then
while(x.isAlive())
{
Thread.sleep(1000);
}
to try and ensure this, but I'm worried this could be the cause of my problem too.
I've been looking everywhere for some pointers, but since I can't find any I'm sure I'm doing something stupid here.
The problem is, your long running task is blocking the Thread that keeps the GUI responsive.
What you will need to do is put the long running task on another thread.
Some common ways of doing this are using Timers or a SwingWorker.
The Java tutorials have lots of information regarding these things in their lesson in concurrency.
To make sure the first task finishes before the second, just put them both on the same thread. That way you won't have to worry about keeping two different threads timed correctly.
Here is a sample implementation of a SwingWorkerFor your case:
public class YourTaskSwingWorkerSwingWorker extends SwingWorker<List<Object>, Void> {
private List<Object> list
public YourClassSwingWorker(List<Object> theOriginalList){
list = theOriginalList;
}
#Override
public List<Object> doInBackground() {
// Do the first opperation on the list
// Do the second opperation on the list
return list;
}
#Override
public void done() {
// Update the GUI with the updated list.
}
}
To use this code, when the event to modify the list is fired, create a new SwingWorker and tell it to start.
You are not returning the swing thread properly. I realize you are using callable/runnable but i'm guessing you are not doing it right (although you didn't post enough code to know for sure).
The basic structure would be:
swingMethod() { // Okay, this is a button callback, we now own the swing thread
Thread t=new Thread(new ActuallyDoStuff());
t.start();
}
public class ActuallyDoStuff() implements Runnable {
public void run() {
// this is where you actually do the work
}
}
This is just off the top of my head, but I'm guessing that you either aren't doing the thread.start and are instead calling the run method directly, or you are doing something else in the first method that locks it up (like thread.join). Neither of these would free up the swing thread. The first method MUST return quickly, the run() method can take as long as it wants.
If you are doing a thread.join in the first method, then the thread is NOT being returned to the system!
Edit: (Second edit actually)
I think to speak to the problem you are actually feeling--you might want to think more in terms of a model/view/controller system. The code you are writing is the controller (the view is generally considered to be the components on the screen--view/controller are usually very tightly bound).
When your controller gets the event, it should pass the work off to your model. The view is then out of the picture. It does not wait for the model, it's just done.
When your model is finished, it needs to then tell the controller to do something else. It does this through one of the invoke methods. This transfers control back to the controller and you go on your merry way. If you think about it this way, separating control and deliberately passing it back and forth doesn't feel so bulky, and it's actually very common to do it this way.
It sounds like the problem might be that you are waiting on the threads to finish from inside the GUI thread. Your GUI thread should not wait on these threads, instead you should have the worker threads invoke some method on the GUI thread that sets a flag. When both flags are set then you know both threads finished and you can do the graph.
I can't really speak to the swing threading model, but:
I have to do the two processing stages in order too, so what is the best way to ensure the second one has waited on the first?
For this kind of functionality, I'd suggest you create two worker threads, and embed a JMS broker. Deliver work to the two threads by passing messages into JMS queues that they read from. Your GUI thread is free to examine the queues to determine when work is happening and represent the state of play in your UI.
The solution to my problem was a mixture of jjnguy and Bill K's answers, so thanks very much for that guys. I needed to use threads within a SwingWorker like this:
public class Worker extends SwingWorker<Void, Void>
{
private List<Object> list;
public YourClassSwingWorker(List<Object> theOriginalList){
list = theOriginalList;
}
#Override
public List<Object> doInBackground() {
Thread t = new Thread(new ProcessorThread(list));
t.start();
}
#Override
public void done() {
// draw graph on GUI
}
}
class ProcessorThread implements Runnable {
//do lots of IO stuff
Thread t2 = new Thread(new SecondProcess());
t2.start();
}
This made sure all the work was being done by worker threads away from the GUI, and also ensuring that the SwingWorker itself wasn't doing all of the work, which might have been a problem.

Categories

Resources