Pausing Threads From Events

B

Bryan R. Meyer

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
 
K

Knute Johnson

Bryan said:
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

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
}
 
R

Roedy Green

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
 
R

Rob Shepherd

Bryan said:
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

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
 
B

Bryan R. Meyer

Roedy Green said:
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
 
R

Rob Shepherd

Bryan said:
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

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
 
N

NOBODY

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);


}

}











(e-mail address removed) (Bryan R. Meyer) wrote in
 
R

Rob Shepherd

NOBODY said:
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
-----------------------------------------------------------------------------
 
A

Ade

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
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);


}

}











(e-mail address removed) (Bryan R. Meyer) wrote in

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
 
B

Bryan R. Meyer

Rob Shepherd said:
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
 
C

Carl Howells

Bryan said:
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.
 
A

Andrew Thompson

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.
 
R

Roedy Green

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.
 
R

Roedy Green

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.
 
K

Knute Johnson

NOBODY said:
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)

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.
 
N

NOBODY

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...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top