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.
Related
I'm very new to multithreading - I've done a few hours of research and tested a few different ways. I've recently implemented this code:
public class resetDataThread implements Runnable {
VertexHashMap allVertices;
public resetDataThread(VertexHashMap allVertices){
this.allVertices = allVertices;
}
#Override
public void run() {
for (int i = 0; i < allVertices.data.length; i++)
{
if (allVertices.data[i] != null){
allVertices.data[i].inClosed = false;
allVertices.data[i].inOpen = false;
}
}
System.out.println("Thread Finished!");
}
}
Please note, VertexHashMap is a self implemented hash map that stores Vertices.
Runnable r = new resetDataThread(allVertices);
Thread t1 = new Thread(r);
I call the method like so:
t1.run();
This line of code gets called many times without creating new instances of r or t1.
My reason for implementing this is so my program can fetch new data and output results while it resets the storage's boolean variables (allVertices). My main aim is execution speed of my program, so I figured I could multi thread this section of code.
So my question is, is this safe, suitable or a good way to do this?
Example
...code that changes allVertices variables
t1.run(); //this will run while otherSectionOfProgram and yetAnotherSectionOfProgram is executed
otherSectionOfProgram();
yetAnotherSectionOfProgram();
The example above can be called many times however the contents of allVertices will always be the same (except for the boolean settings), so I'm just wanting to make sure it's okay to use the run() method the way I have - as I want to ensure I practise good java/programming.
If what you're after is to have a single background thread running then call t1.start() to start a background thread.
If you want to get more advanced with creating threads look into the Executor Service for java Java Executor Service
It's also worth noting that unless allVertices is pretty large in size it shouldn't take much time to run the run() method anyway, but it's easy enough to time it to see how much difference it makes.
EDIT:
Also make sure otherSectionOfProgram(); and yetAnotherSectionOfProgram(); do not modify allVertices if you aren't creating a new instance of that because your background thread will be operating on it as well.
t1.run();
This line of code gets called many times
Call start() on your thread, not run().
What's the difference between Thread start() and Runnable run()
You start created threads with t.start() method, t.run() won't start a new thread.
Also, calling t.start() multiple times still won't create a new thread each time it's called, your thread t is unusable(dead) after it's done once. You need to create new Thread for every ... well... thread.
For starting new thread you should call start() method.
For program safety, you should take care about mutual exclusion, I should know logic of program to advise you more about the correct solution, but you may want synchronize allVertices if another sections of program may change it simultaneously or if you want to create more than one instance of your thread:
#Override
public void run() {
synchronized(allVertices){
for (int i = 0; i < allVertices.data.length; i++)
{
if (allVertices.data[i] != null){
allVertices.data[i].inClosed = false;
allVertices.data[i].inOpen = false;
}
}
}
System.out.println("Thread Finished!");
}
OK, first of all, calling Thread.run() will not start a new Thread. It will run the method on the calling thread. To actually start a new thread you have to use Thread.start(). In the code you posted there is no multithreading happening.
Secondly, the line VertexHashMap is a self implemented hash map that stores Vertices. screams non-thread-safe to me. You know there is a special ConcurrentHashMap version of HashMap to deal with concurrent (i.e. multithreaded) use? Which structure did you base your class on? Did you make your own objects thread-safe? Inter-thread visibility problems may arise.
Thirdly, reusing threads is tricky business. Just calling run multiple times won't even make a single Thread, but calling start more than once will throw an exception. As some of the other answers pointed out - using an ExecutorService is a great alternative - you can set it up to use whatever number of threads you want (and have flexibility in how it behaves under load), and have it reuse its threads (instead of re-inventing the complex machinery behind it).
Finally - you may want to think about visibility of your objects. In your case you have the VertexHashMap as default visibility. This means that other classes can see and use it directly. This may be a problem if, for example, you are in the process of clearing it, or re-populating. Then the user gets a half-ready object, whose methods may easily fail. Java has a Future interface just for that - it's an interface to be used with multithreading that "promises" to return a ready object. It's the basis for Swings SwingWorker and Androids AsyncTask - objects that do tasks in the background thread, and then return ready results to the foreground for further use.
Say I have something like this (and I do)
class QueBean extends JPanel {
private Queue queue = new LinkedBlockingQueue();
public Object poll(){
return queue.poll();
}
}
with some of these that run on their own threads
class ConsumerBean extends JPanel implements Runnable{
private QueBean queBean;
public synchronized run(){
while (true) {
Object result = queBean.poll();
if (result != null) {
jResultTextField.setText("got one");
}
wait(500);
}
}
}
Should my poll() in the QueBean be synchronized or not?
There is a threading problem, but not the one you think--The code you posted is almost certainly illegal and will eventually lock up.
One of the core rules of Swing is that only one thread is allowed to touch "realized" components. (Realized means on-screen or "almost" on-screen).
This:
jResultTextField.setText("got one");
Inside a thread is pretty sure to be wrong--you just can't do it. Check out invokeLater or invokeAndWait to get your screen updates onto your AWT thread.
By the way--it feels funny having threads in anything that extends a component--seeing that lead me to IMMEDIATELY search for where the conflict was, but it should make any long-time Java programmer uneasy at a glance--I suggest you split up your classes some and completely separate the part that drives your GUI (Controller) from the GUI (View)..
External synchronization is not necessary in this case. Read the BlockingQueue contract:
BlockingQueue implementations are
thread-safe. All queuing methods
achieve their effects atomically using
internal locks or other forms of
concurrency control.
No. There is no need. Since your poll method does nothing except call a thread-safe method, there is no possibility of data corruption.
You don't need to do this, so long as queue does not change in QueBean.
Also, unless you're trying to implement some kind of trivial rate-limitng, you don't need the wait(500) in your code. It's superfluous due to the queue being blocking.
I've got a question related but not identical to my first question ever here:
Java: what happens when a new Thread is started from a synchronized block?
Is it a common practice to create and start() a new Thread when you're holding a lock?
Would that be a code smell?
Basically I've got a choice between doing this:
public synchronized void somemethod() {
(every time I find a callback to be notified I start a thread)
Thread t = new Thread( new Runnable() {
void run() {
notifySomeCallback();
}
}
t.start();
...
(lengthy stuff performed here, keeping the lock held)
...
}
or this:
public void somemethod() {
(create a list of callbacks to be notified)
synchronized(this){
(potentially add callbacks)
...
(lengthy stuff performed here, keeping the lock held)
...
}
(notify the callbacks without holding a lock and once
we know the lock has been released)
}
I think the latter is better but I wanted to know if there
are cases where the first option would be ok? Do you sometimes
do that? Have you seen it done?
answer3:
You should always hold on to a lock as short as possible. So only the resource which is potentially referenced to from multiple threads should be locked for the smallest amount of time when the chance of a 'corrupt' resource exists (e.g. the writer thread is updating the resource)
Don't spin off a thread for every little thing which needs to be done. In the case of your callback threads, have 1 callback thread work off a queue of things to do.
You are aware that the two code snippets will result in different execution orders.
The first one will run the callbacks asynchronously, while the lengthy stuff is being performed. The second one will finish doing the lengthy stuff first and then call the callbacks.
Which one is better depends on what the callbacks need to do. It might well be a problem if they need lengthy stuff to be done first.
Who is waiting on the lock?
If the callbacks need the lock to run, it makes little sense to fire them, while you still hold the lock. All they would do is just wait for lengthy stuff to be done anyway.
Also, in the first snippet, you have one thread per callback. The second snippet is not explicit, but if you have only one thread for all of them, this is another difference
(whether the callbacks run simultaneously or in sequence). If they all need the same lock, you might as well run them in sequence.
If you want to run many callbacks with one or more threads, consider using an Executor instead of managing the threads yourself. Makes it very easy to configure an appropriate number of threads.
It depends on whether or not you want the callbacks to be executed concurrently with the lengthy stuff or not. If we are talking about a Swing GUI, option 1 is not good, because you shouldn't do Swing operations in several concurrent threads, so I propose the following:
public void somemethod() {
Thread t = new Thread( new Runnable() {
void run() {
doLengthyStuff();
}
}
t.start();
(notify the callbacks)
}
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.
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.