Stopping Threads by the book?

Hello,

when doing some programs with threads, I got the feeling, that the documentation of the

API is not quite in line with the tutorials on this site. Also, the two books on Java that I read

do not suggest the same solution to stopping a thread (using interface runnable).

Essentially, the tutorials suggest to use some instance variable (here clockThread) to signal a thread it should stop itself. In addition, a "try/catch" block is used when sleep() or wait() is in use:

public void run() {

Thread myThread = Thread.currentThread();

while (clockThread == myThread) {

repaint();

try {

Thread.sleep(1000);

} catch (InterruptedException e){

// the VM doesn't want us to sleep anymore,

// so get back to work

}

}

}

Reading the API, I would have thought, that just using the interrupt() method on my thread in

combination with a check "isInterrupted"the "try/catch":

public void run() {

myThread = Thread.currentThread();

while (!myThread.isinterrupted()) {

repaint();

try {

Thread.sleep(1000);

} catch (InterruptedException e){

// the VM doesn't want us to sleep anymore,

// so get back to work

}

}

}

Questions:

1. Of course, version 2 would be slower (depends on how often the loop is executed). But are there any other reasons, why it should not be used? If version 1 is better, for what are the "interrupt" methods in the API good? Isn`t version 2 inherently safer and more portable?

2. Performance: Wouldn't it be better to put the whole "while"-loop into the try-block? As long as the exact source of the exception doesn`t matter, wouldn't that be faster?

What do you think?

[1831 byte] By [Phenningsen] at [2007-9-26 3:09:18]
# 1

I think that the isInterrupted method could cause problems, because if the thread is interrupted twice then i think it is reset.

What exactly are you trying to do ?

If youare waiting for some event then try the

synchornized(lockObject)

{

lockObject.wait();

}

and use notify to interrupt the thread. Also you should try putting some sort of variable to check if the thread should stop.

scottcoleman1973 at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 2

I think the second version can actually be faster because calling interrupt() on your thread instead of 'clockThread=someDifferentThread' will result in the loop being stopped immediately. With the assignment, you will need to wait out the entire Thread.sleep() call before you will exit. For example, if you finish repaint() and someone does the 'clockThread assignment' while you start the Thread.sleep() call, you would have to complete the entire sleep() call even though you could save a few milliseconds by leaving early.

As far as the flow of control goes, I don't think that catching the InterruptedException outside of the loop will help you much. Maybe it will save you an isInterrupted() call if Thread.sleep() is interrupted and you jump right to your exception handler instead of to the top of the loop. You probably would move the exceptions out of the while loop if you have other sleep calls in the loop to that you wouldn't be catching a lot of exceptions and cluttering your code.

CWalker807 at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 3

Hello, and thank you for your answer!

Well, what am I trying to do? Just to find out, what way to stop a thread on demand is most reliable and efficient! BTW, the thread is doing something, so there may be a sleep() or just a yield() in this loop. At the core of my question is really: Should I introduce an additional variable

per thread for signaling the stop, or may I do without it.

With regards to your remark "...because if the thread is interrupted twice then i think it is reset.",

the API says:

-

isInterrupted

public boolean isInterrupted()

Tests whether this thread has been interrupted. The interrupted status of the thread is unaffected by this method.

Returns:

true if this thread has been interrupted; false otherwise.

See Also:

interrupted()

I am not using the class method "interrupted()" of Thread, which does reset the flag. That one is

certainly unreliable in my context.

Phenningsen at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 4

Thanks to you als well,

actually, in terms of reaction time, I think both versions perform very similar, as they both do poll a status flag or react to an interrupt-exception.

The important difference to look at is the performance of the while() - loop (after all, it does the work!). And there version 2 would be less efficient because it contains an additional method call, right?

To re-phrase my question 2 : What is the overhead to establish an exception handler? If the "try" is within the loop, the handler is established in every pass. If the loop is within the the try-block, it would be established once, which should be a lot more efficient, right?

Or is there a potential problem with nesting try-blocks (if I do some real work in the loop and use try-blocks for IO or Math-exceptions)?

Phenningsen at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 5

What do you think about this one?

public void run()

{

try{

for(;;)

{

Thread.sleep(1000);

repaint();

}

}

catch(InterruptedException ex)

{

}

}

Just interrupt the thread to stop it! For your particluar purpose this might be the best solution, don't you think?

";-)

Ragnvald Barth

Software engineer

Ragnvald at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 6

Version one is not guaranteed to work in all implemenations, unless you declare the signalling variable as volatile. This is a good example of a basic issue: if the API does something for you, use it, becuase it has (almost always) been done right. The performance issue is trivial, and may well be zero in a good JVM.

Unfortunately there is a problem: NN4 does not support Thread.interrupt(). Only Thread.stop() will work.

By the way, you may find that your animation is a bit jerky, especially in IE, since Thread.sleep() guarantees to sleep for at leadt the time you specify, but does nto return promptly. To get really smooth results, you need to get the current time in the paint routine.

chrishmorris at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 7

Well,

I would not trust this solution: It looks good, however, as far as I know the interrut exception will only get thrown by sleep(). If the interrupt hits when repaint is running, it has no effect. And as this loop does not check for the interrupt flag, it may be that the tread ignores the request completely. A bit like gambling: If sleep() runs long compared to repaint() your chances are good for this to work, otherwise not.

Right?

Phenningsen at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 8

Thanks for your input!

Yes, I read about using "volantile". And I assume, the method in the API would take care of such details.

Performance impact == Zero? You mean the setup of the exception handler, right? As elsewhere I read, that the overhead of method invocation is pretty big.

Does NN4 support the instance method "interrupt()"? I do not use the class method.

Regarding animation: In animations I would not use sleep(), but yield() combined with a suitable

priority or a wait/notify to sychronise with other tasks. The code provided here is just the example

from the tutorial, not what I work on.

Phenningsen at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 9

why not just use a boolean flag such as the following:

public boolean stop_ = false;

public void stop(){this.stop_ = true;}

public void run(){

while(stop_ == false){

}

}

if you need to stop the thread, just call the stop() method. Although this approach means the thread has to finish a loop, it means the thread can be stoped within a known state.

rob

rbyrom at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 10
I thought that using interrupt and that is not exactly great because if you interrupt it when its holding onto a resource you cant do anything else. The flag as shown in the last post is the way 2 go
cpc9 at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 11
Thank you all,I think, we close it here. Looks, like everyone does a solution with their own flag variable andmost distrust the flag in the Thread class (or just don't know about it).Thanks a lot,Peter
Phenningsen at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 12

Last word goes to me then?

If you keep your own flag you can still use interrupt.

(first clear your keepRunning flag, then call interrupt)

If interrupt doesn't work the current loop will finish, and then the thread will stop, so it's going to work anyway. My expirience is that animation is smoother without System.currentTimeMillis() in the paint().

You might call the System.currentTimeMillis() onece in a while just to adjust the sleeping time to your computers performance though. As I have done in this example:

http://blake.prohosting.com/ragnvald/

Thread.stop() is not a good idea, because it is deprecated, and will throw an exception in NN6.

try{Thread.stop()}

seems to work ok (for the time beeing), but it's not a good idea to use deprecated methods. (First they are deprecated for a reason, second they might stop working with a newer jvm)

Ragnvald at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...
# 13
Sorry to butt in ,but I have a similar problem ,my animations go jerky and then stop alltogether after some time. I am using IE. Any ideas what do I do.Jayanti
jayantis at 2007-6-29 11:14:56 > top of Java-index,Core,Core APIs...