Java Forum / First Aid / April 2004
Pausing Threads From Events
Bryan R. Meyer - 27 Apr 2004 03:39 GMT Hello Everyone,
Hopefully, someone has some pointers for my problem. Suppose I have an applet which starts a new thread A. The applet implements MouseListener and when the user puts the mouse over the applet, a MouseEvent occurs. When a user generates this MouseEntered event, thread A is to be paused. Unfortunately, the currently executing thread is AWT-EventQueue. How can I pass that event to thread A so that I can pause the thread?
Thanks for any suggestions. I haven't been able to find much on this subject.
Bryan
Knute Johnson - 27 Apr 2004 04:08 GMT > Hello Everyone, > [quoted text clipped - 10 lines] > > Bryan Create a volatile boolean for a flag and set the flag in your listener code. In the run() of your thread, test the flag, if it is true, pause.
class ??? { volatile boolean flag = false;
// Listener code flag = true;
// run() if (flag) // pause }
 Signature Knute Johnson email s/nospam/knute/ Molon labe...
Roedy Green - 27 Apr 2004 04:31 GMT > How can I pass that event to thread A so >that I can pause the thread? You never pause the AWT thread that handles an event. If it has something lengthy to do, it should spin off a new thread, or signal some other already running thread to do the work.
While you are in your event handler nothing else in the GUI can happen, no mouse clicks, no http://mindprod.com/jgloss/thread.html
-- Canadian Mind Products, Roedy Green. Coaching, problem solving, economical contract programming. See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Bryan R. Meyer - 27 Apr 2004 22:10 GMT > You never pause the AWT thread that handles an event. If it has > something lengthy to do, it should spin off a new thread, or signal > some other already running thread to do the work. I suppose I wasn't as clear as I should have been. I DO NOT wish to pause the AWT thread. I wish to pause thread A. However, if the user generates a MouseEvent, and in the event handler I call a method - pauseThread() - to pause the thread by doing a wait(), the result is a IllegalMonitorStateException: current thread not owner. In this case, the AWT thread is still handling the event so thread A can't wait. My question was how can I pause thread A as a result of the MouseEvent despite the fact that the AWT event thread is the currently executing thread?
Rob's code seems to make sense, but in his object B, he seems to have a busy wait when he checks to see if the thread is paused. Or is this not a busy wait since the thread (and loop) are blocked when wait() is called in the loop? Can this be avoided?
while(paused) { try { wait(); // this object is now paused.... } catch (Exception e) { } } Thanks, Bryan
Rob Shepherd - 28 Apr 2004 12:45 GMT >>You never pause the AWT thread that handles an event. If it has >>something lengthy to do, it should spin off a new thread, or signal [quoted text clipped - 25 lines] > Thanks, > Bryan This part if the thread just checks to see if paused is true. If it is then the thread will pause inside the wait() function.
Ie. the wait() method does not return immediatly. the wait() method returns when the object has been notified and the lock(b) is available for other classes again.
I find this code works for loops which take a medium amount of time to complete. Too long and then user will have to wait until the end of the nonpaused section to see the pausing effect.
Imaging if there were a blocking section in the nonpaused bit. if it were paused whilst in this blocked area of code the Thread would appear paused but then when the blocked bit comes free, you would see the remaining code execute THEN it would pause!!.
having while(paused) instead of if(paused) is better because wait() can be interrupted. If it does get interrupted then it will just wait again.
good luck
rob
Bryan R. Meyer - 28 Apr 2004 22:19 GMT > This part if the thread just checks to see if paused is true. > If it is then the thread will pause inside the wait() function. Makes sense. The thread is essentially blocked and, therefore, paused.
I appreciate the help. I don't quite understand the response given by NOBODY. This is not for a professional project; it is merely for a small personal project. I can't understand why such a function for pausing threads is not already in the language. (Of course, I noted the deprecation of suspend().)
Thanks again, Bryan
Carl Howells - 28 Apr 2004 22:31 GMT > I appreciate the help. I don't quite understand the response given by > NOBODY. This is not for a professional project; it is merely for a > small personal project. I can't understand why such a function for > pausing threads is not already in the language. (Of course, I noted > the deprecation of suspend().) I can explain this one... But I may not need to. You say that you noted that suspend() is deprecated. But did you read the rather large document Sun put together explaining why many of the methods in Thread are deprecated? It explains rather well.
As a simple recap, suspend() is dangerous. If you can arbitrarily suspend another thread at any point in its execution, you can create deadlocks. Requiring that the thread implement code to pause itself safely (releasing all necessary locks, and making sure all data structures it was using are in internally consistent states) increases the safety of the threading system significantly.
Roedy Green - 29 Apr 2004 01:22 GMT > I can't understand why such a function for >pausing threads is not already in the language. There was, then they discovered it did not always work. So they deprecated it all.
You can try something like StoppableThread.
See http://mindprod.com/products.html#BUS part of the business package.
-- Canadian Mind Products, Roedy Green. Coaching, problem solving, economical contract programming. See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Rob Shepherd - 27 Apr 2004 09:36 GMT > Hello Everyone, > [quoted text clipped - 10 lines] > > Bryan I paused a thread in this manner:
two ojects A and B. A is a gui and pauses/resumes Thread B.
thus in class A
[two buttons start and stop] ... b = new B(); b.start();
stop.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { synchronized(b) { b.paused = true; } stop.setEnabled(false); start.setEnabled(true); } } );
start.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { synchronized (a) { b.paused = false; b.notify(); } start.setEnabled(false); stop.setEnabled(true);
} } ); ...
[in the class for object b (above)]
... public boolean paused = false;
public void run() { while(true) { synchronized(this) { while(paused) { try { wait(); // this object is now paused.... } catch (Exception e) { } } }
////Here i do some stuff when not paused
}
} ...
regards
NOBODY - 28 Apr 2004 13:25 GMT Yes, I got answers for you. I'm sorry to tell you the following but you should mostly ignore the answers you got. These techniques are not professionnal. Period.
1st, you sure will have a boolean to change/check somewhere, but the volatile keyword (that supposably protects threads from processor caching) is not implemented in many jvm. You may easily confirm that hot topic with a simle search on the web.
2nd, the only sure way to do "messaging" between threads required the use of a "synchronized" zone, that forces the thread fo resync with memory. This is critical in multiprocessors platforms.
3rd, your thread to be paused need to cooperate, i.e. it must be ready to be notified or capable to handle interruptions (only one of the 2 technique is enough, and I suggest you go with notifiations, it is less work, although you might want to combine both)
----------- package tests;
import java.io.InterruptedIOException;
public abstract class PausableLoopThread extends Thread {
long delay; //critical zone 1:----- final Object lock = new Object(); boolean paused = false; boolean running = false; //--------------------- boolean requestedInterrupt = false;
public PausableLoopThread(String name, long delay) { this(null, name, delay); }
public PausableLoopThread(ThreadGroup group, String name, long delay) { super(group, name); if(delay<=0) throw new IllegalArgumentException("delay <= 0"); this.delay = delay; }
public final void interrupt() { requestedInterrupt = true; super.interrupt(); }
public final void run() { synchronized(lock) { running = true; } while(true) { boolean _p; synchronized(lock) { if(!running) break; _p = paused; } //unlock zone to process loopImpl, otherwise changePause() would block while loopImpl() running (may be long) if(!_p) { try { loopImpl(); } catch(InterruptedException e) { if(!requestedInterrupt) System.err.println("Thread was interrupted by another unexpected way!"); break; } catch(InterruptedIOException e) { if(!requestedInterrupt) System.err.println("Thread was interrupted by another unexpected way!"); break; } catch(Exception e) { if(requestedInterrupt) { //detect stupid 3rd party that do not rethrow Interrupts System.err.println("Thread was interrupted but didn't throw InterruptedException: "+e); //e.printStackTrace(); break; } else { e.printStackTrace(); } } } synchronized(lock) { try { lock.wait(paused ? 0 : delay); //gets out by timeout of by notify } catch(InterruptedException e) { if(!requestedInterrupt) System.err.println("Thread was interrupted by another unexpected way!"); break; } } } }
protected abstract void loopImpl() throws InterruptedException, InterruptedIOException;
public final void requestPause() { changePause(true); }
public final void requestResume() { changePause(false); }
private void changePause(boolean pause) { synchronized(lock) { boolean b = this.paused; this.paused = pause; //if(!pause && b!=pause) //notify only if resumed, why waking up a waiting thread! lock.notify();//kick out of wait } }
public final void requestStop() { synchronized(lock) { this.running = false; lock.notify();//kick out of wait, if any } }
//======== public static void main(String[] args) throws Exception{ PausableLoopThread p = new PausableLoopThread("pt", 300) { final long t0 = System.currentTimeMillis(); protected void loopImpl() throws InterruptedException, InterruptedIOException { System.out.println("loop it! "+ (System.currentTimeMillis()-t0)); } }; p.start(); Thread.sleep(4000); p.requestPause(); Thread.sleep(4000); p.requestResume(); Thread.sleep(4000); p.requestStop(); //p.interrupt(); Thread.sleep(4000); } }
> Hello Everyone, > [quoted text clipped - 10 lines] > > Bryan Rob Shepherd - 28 Apr 2004 15:09 GMT > Yes, I got answers for you. > I'm sorry to tell you the following but you should mostly ignore the > answers you got. These techniques are not professionnal. Period. So only Java "Professionals" are allowed to post messages with fully working endorsed guaranteed to work *this-what-you-MUST-do* code examples eh?
I was under the impression that these newsgroups provide simple help for people who need (amongst other things) a gentle push in the right direction. The original poster, Bryan R Meyer, clearly has little experience with Threads and the Thread model otherwise he would have included a code excerpt from his problem. His statement "Hopefully, someone has some pointers for my problem" made me think...
1. I have done this before. 2. I have a simple solution working. (which works all day every day as part of reliable system [on a multiprocessor machine]) 3. It would be easy to copy-paste into a reply 4. Maybe he (and others) might benefit/learn more/take it further.
If only professional Java programmers were allowed to respond then i would imagine the useful traffic would be rather small compared to requests-for-help from students, hobbyists, academics, scientists etc.
If only code which is 100% guaranteed to satisfy the needs of the request was allowed then I think not many people would be bothered to reply.
Frankly I find your attitude rude, pompous and totally against the spirit of these newsgroups.
Granted your code is well written, is the perfect solution and would be the kind of code one would expect as an example in a latter chapter of a book on Threading. Nevertheless don't you agree that books require early chapters, with simple examples, to ease the learner into the new concepts?
I imagine your post is appreciated by Bryan but why not try an opening paragraph such as..... --- Hi, I have a fairly comprehensive solution. My example below makes use of synchronization and is safe for use on multi processor machines.
Hope this helps
NOBODY ---
Sorry for the rant. You try and help people and "lord-god-of-Threading-upon-high" has to go and beat you down....
regards
Rob
----------------------------------------------------------------------------- I'm sorry to tell you the following but you should mostly ignore [this] These techniques are not professional. Period.
- NOBODY 2004 -----------------------------------------------------------------------------
Roedy Green - 29 Apr 2004 10:28 GMT >> I'm sorry to tell you the following but you should mostly ignore the >> answers you got. These techniques are not professionnal. Period. > >So only Java "Professionals" are allowed to post messages with fully working >endorsed guaranteed to work *this-what-you-MUST-do* code examples eh? keep in mind this is comp.lang.java.help THE place for newbies. Cut everyone some slack.
-- Canadian Mind Products, Roedy Green. Coaching, problem solving, economical contract programming. See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Ade - 28 Apr 2004 15:30 GMT Is it really necessary to criticize other people's solutions? I've looked at this instance and seen code that is a lot less bloated than yours and satisfies certainly conditions 2 and 3 that you state.
I thought the beauty of Java was that there are so many different ways to do things - and no single way is better than all others, it's simply different. The days of requiring perfect code that conforms to such conditions are gone, and thank god that is so because at least now the focus can increasingly be ideas and imagination rather than the details of implementation.
Have a nice day A
> Yes, I got answers for you. > I'm sorry to tell you the following but you should mostly ignore the [quoted text clipped - 178 lines] >> >>Bryan Andrew Thompson - 29 Apr 2004 09:38 GMT > Is it really necessary to criticize other people's solutions? Is it really necessary to repost 197 lines of the former post to ask that?
Please have a look over the entry after 'top-post' <http://www.physci.org/codes/javafaq.jsp#netiquette>
While we are on the subject, and in answer to your question.
"Yes"
This is a technical group (checks) OK - I realise now it is going to both c.l.j.programmer _and_ c.l.j.help
That complicates things..
Such 'rough and tumble' comments would usually go by on c.l.j.p without raising a single eyebrow, but converstaions on c.l.j.h are usually conducted in a much more sensitive manner.
Ultimately though, most people come to the groups to get the best possible solution, rather than to have a nice, polite chat.
In defence of the specific statement "I'm sorry to tell you the following but you should mostly ignore the answers you got. These techniques are not professionnal. Period."
There are times you need to make a definitive statement, at the top of the post, that other solutions offered (no matter how well intentioned) are not the way to go.
( And as far as 'polite' goes, I do not see how you could both achieve the 'definitive statement' and be any more polite.. )
If you have any particular disagreements with technical aspects of the code provided, discuss them, otherwise celebrate that you have now been shown some extra tips.
 Signature Andrew Thompson http://www.PhySci.org/ Open-source software suite http://www.PhySci.org/codes/ Web & IT Help http://www.1point1C.org/ Science & Technology
Roedy Green - 29 Apr 2004 10:31 GMT >Is it really necessary to criticize other people's solutions? YES YES YES. If people post code everyone should be pointing out ways to improve it. People learn from copying. If you let sloppy code pass, you teach sloppy coding. However, there is no need to be nasty.
Engineers and computer scientists have to learn to get ego out the way. You NEED peer review to get the bugs and and to improve.
Thin skinned people can never become great programmers.
Think of it as a game to polish each bit of code that gets posted to perfection.
-- Canadian Mind Products, Roedy Green. Coaching, problem solving, economical contract programming. See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Knute Johnson - 29 Apr 2004 23:40 GMT > Yes, I got answers for you. > I'm sorry to tell you the following but you should mostly ignore the [quoted text clipped - 13 lines] > technique is enough, and I suggest you go with notifiations, it is less > work, although you might want to combine both) Why would you use a non-compliant JVM or are we talking the 'Dark Side' here? The use of volatile that I suggested would I believe work just fine as it would not be affected by any of the known memory reordering issues. Bryan asked how to communicate the pause message from his MouseListener to his running thread. There is nothing unprofessional about setting a flag to do that. He didn't define what he meant by pause and could have just wanted to sleep for a few milliseconds.
Your PauseableLoopThread, while a brilliant and professional masterpiece of Java coding, is probably serious overkill for what Bryan needed.
 Signature Knute Johnson email s/nospam/knute/ Molon labe...
NOBODY - 30 Apr 2004 01:57 GMT I'm sorry Knute, Rob, Ade. I didn't meant to offend you.
Thanks Roedy, Andrew. I also feel some groups are dedicated to experts, because, unlike newbies, we can't find books and hundreds of web pages to tell us the answer at chapter 2.
>I thought the beauty of Java was that there are so many different ways >to do things - and no single way is better than all others, it's simply >different. Well, that is just not true. And java has nothing to do with it. This was about concurrent programming, not swing GUIs.
Besides, experts usually end up sharing the same vision for an architecture/implementation because they learned the do's and don't of programming. This forum helps accelerate the process.
I wanted to be precise and underline some threading issues by the same medium. Judging by some critics, I didn't miss my goal...!
I mostly wanted to underline that no one should wait() without using notify ()/notifyAll(), and Thread.sleep() should not even exist. There is nothing worse (relatively speaking) than a thread stuck somewhere ureachable...
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|