Thread not responding to stop()

Hi, i'm in the midst of writing my first application, a Blackjack game. I'm having a problem with InterruptedExceptions being thrown when I call Thread.sleep() from within one of my threads.

Is there a way I can find out which thread is being interrupted by which other thread?

Upon running the Java debugger, i've noticed that the thread number continually increases. It gets greater as I run the application and never stops increasing, like so:

Thread-3[1] next

>

Breakpoint hit:"thread=Thread-4", BlackjackPanel$CardPanel.run(), line=453 bci=

0

453if (doDealAnimation)

Thread-4[1] next

Here's an example of how I call stop() and the following line is still executed:

Step completed:"thread=Thread-3", BlackjackPanel$CardPanel.run(), line=533 bci=

417

533stop();

Thread-3[1] next

>

Step completed:"thread=Thread-3", BlackjackPanel$CardPanel.run(), line=534 bci=

421

534return;

The complete source for this application is at: http://kouellette16.home.comcast.net/MyBlackjackGame__6-13-07.zip

Thank you for your time.

[1294 byte] By [kwiknessa] at [2007-11-27 7:34:08]
# 1
[url= http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html#stop()]Thread.stop() is deprecated[/url].Click [url= http://java.sun.com/j2se/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html]here[/url] to see why.
kevjavaa at 2007-7-12 19:14:33 > top of Java-index,Java Essentials,Java Programming...
# 2

Yeeaahhh... i'm aware of that. I've already overidden the stop method.

private void stop()

{

if (thread != null)

{

thread.interrupt();

thread = null;

//System.out.println("Stopping thread");

}

}

Thanks for the super-helpful post.

kwiknessa at 2007-7-12 19:14:33 > top of Java-index,Java Essentials,Java Programming...
# 3

try:

public class OuterClass {

private InnerThread it;

/* ... */

private class InnerThread extends Thread {

boolean keepGoing;

private InnerThread() {

keepGoing = true;

}

/* ... */

public void run() {

while ( keepGoing ) {

/* ... */

}

}

public void stopIt() {

keepGoing = false;

}

}

/* ... */

public void someOtherMethodThatUsesInnerThread() {

/* ... */

it = new InnerThread();

it.start();

doSomeOtherMethodThatProducesSomeOutcome();

}

private void doSomeOtherMethodThatProducesSomeOutcome() {

/* ... */

it.stopIt();

}

}

abillconsla at 2007-7-12 19:14:33 > top of Java-index,Java Essentials,Java Programming...
# 4
> Yeeaahhh... i'm aware of that. I've already overidden> the stop method. [snip]> Thanks for the super-helpful post.Wow. Somebody's got his tampon stuck crossways today.
jverda at 2007-7-12 19:14:33 > top of Java-index,Java Essentials,Java Programming...
# 5

> Yeeaahhh... i'm aware of that. I've already overidden

> the stop method.

>

> Thanks for the super-helpful post.

Then you're talking about a Runnable, right? Thread.stop() is also final, so you can't override it. If you're implementing a Runnable, then you're not overriding stop().

Thanks for the smart-*** comment, though.

public class DieThread {

class NiftyThread implements Runnable {

private boolean die;

private int blah;

public void run() {

while (!die && blah < 100) {

System.out.printf("\b\b\b\b\b\b\b\b\b\bBlah. %3d%%", blah++);

try {Thread.sleep(10);} catch (InterruptedException e) {/*gulp*/}

}

}

public void stop() {

die = true;

}

}

public DieThread() {

NiftyThread myThread = new NiftyThread();

(new Thread(myThread)).start();

try {Thread.sleep(1000);} catch (InterruptedException e) {/*gulp*/}

myThread.stop();

}

public static void main(String[] args) {

new DieThread();

}

}

EDIT: How about doling out some Dukes, there, tough guy? I'm pretty sure abillconsl solved your problem for you.

kevjavaa at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 6
Thanks for that kev ... OP, why not split em up for us.
abillconsla at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 7

In my opinion and considering the deprecations of the Thread API, I consider using any idea of "stopping" or "killing" a thread to be bad practice. Here's the scenario I would prefer:

public class NiceRunnable implements Runnable {

public void run() {

try {

for(int i = 0; i < 100 && !Thread.currentThread().isInterrupted(); ++i) {

System.out.println(i);

Thread.sleep(10);

}

} catch(InterruptedException e) {

//We must not forget that catching the InterruptedException clears the interrupted flag

//Thus the try/catch has to be outside of the loop

}

}

}

Using this kind of Runnable, all we need to do to get the Thread to stop execution is

Thread t = new Thread(new NiceRunnable());

t.start();

t.interrupt();

And if we wish to block the execution until we are sure that the Thread has completely stopped, we only need to call t.join().

Dalzhima at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 8

Oh and before anyone asks... The reason for using interrupt instead of adding yet another boolean is that the Java API already relies on the interrupted flag to break out of blocking calls such as ServerSocket.accept(), InputStream.read() and so on... So the interrupt solution will work wherever you are inside the execution of a Runnable. Blocked on an API call or running through your own loops.

Dalzhima at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 9

> Oh and before anyone asks... The reason for using

> interrupt instead of adding yet another boolean is

> that the Java API already relies on the interrupted

> flag to break out of blocking calls such as

> ServerSocket.accept(), InputStream.read()

The downside is that the interrupt can occur at any point, so it can be harder to clean up. The boolean lets you control exactly when the thread will be told it's time to stop.

jverda at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 10

> The downside is that the interrupt can occur at any

> point, so it can be harder to clean up. The boolean

> lets you control exactly when the thread will be told

> it's time to stop.

The interrupt can occur at any point, but since you're the one responsible for checking the interrupted flag, it is easy to figure out what cleanup has to be done. Unlike some believe, interrupt doesn't actually stop a Thread, it just raises a flag which should be queried regularly by any Thread so that it knows it has been requested to stop in a deterministic manner.

An example which illustrates this is the following:

public class NastyRunnable implements Runnable {

public void run() {

while(true) {

System.out.println("haha I'm still alive");

}

}

}

Try running this in a thread and then interrupting it and you'll see the result.

Dalzhima at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 11

> > The downside is that the interrupt can occur at

> any

> > point, so it can be harder to clean up. The

> boolean

> > lets you control exactly when the thread will be

> told

> > it's time to stop.

>

> The interrupt can occur at any point, but since

> you're the one responsible for checking the

> interrupted flag, it is easy to figure out what

> cleanup has to be done. Unlike some believe,

> interrupt doesn't actually stop a Thread, it just

> raises a flag which should be queried regularly by

> any Thread so that it knows it has been requested to

> stop in a deterministic manner.

I know there are some conditions when it raises the flag and some when it throws the exception, but I haven't used it for a while, so I don't recall the details.

If it only throws the exception when it's in a blocking call, else raises flag, then yes, we can dispense with the additional boolean.

...

Okay, I just looked. InterruptedException and the various I/O exceptions that can be thrown by interrupt() are checked, so they can't occur anywhere in your code where you're not expecting them.

However, if you want pure flag behavior--that is, if the interrupt occurs while blocked and you want to ignore it, complete that read or whatever, complete that iteration of your loop, and just wrap up at the end, then you'll need to set another flag in the catch block. Or maybe just interrupt() again, which will raise the flag this time?

jverda at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 12

Exactly, the InterruptedException is the way the Java API uses to break out of its blocking methods. It won't be thrown in your face out of the blue.

As for allowing the completion of an iteration of a loop before really interrupting your Thread, you will in fact need another internal flag of yours. Although this still is better than the previous approach with a custom stop method since calling interrupt will allow you to break out of your own code, or to break out of a blocking API call. On the other hand, the stop method shown earlier wouldn't make it possible to break out of a blocking API call.

Finally, another advantage of relying on "interrupt" to stop a Thread is that you can benefit from the abstraction of handling a Collection of Threads and stop them without knowing any specific implementation details such as a custom stop method.

I think I'll write an sdnshare article on the subject ;)

Dalzhima at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 13
Boise I da know ... Joshua Bloch seems to use the older method alot in his section on Threading.
abillconsla at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 14

> As for allowing the completion of an iteration of a

> loop before really interrupting your Thread, you will

> in fact need another internal flag of yours.

Nope. Just call interrupt() in your catch block and test interrupted() at the end (or beginning) of your loop. See code below.

:-)

> Finally, another advantage of relying on "interrupt"

> to stop a Thread is that you can benefit from the

> abstraction of handling a Collection of Threads and

> stop them without knowing any specific implementation

> details such as a custom stop method.

Although you do have to know that they respond to interrupt properly. Still a good point though.

import java.util.*;

public class InterruptTest {

public static void main(String[] args) throws Exception {

Random rand = new Random();

while (true) {

Thread th = new Thread(new Task());

th.start();

Thread.sleep(rand.nextInt(200) * 10);

System.out.println("main interrupting task");

th.interrupt();

th.join();

}

}

}

class Task implements Runnable {

public void run() {

while (true) {

System.out.println(new Date());

try {

Thread.sleep(250);

}

catch (InterruptedException exc) {

System.out.println("Interrupted, re-interrupting");

Thread.currentThread().interrupt();

}

for (int ix = 0; ix < 200000000; ix++) {

int jx = ix * ix;

if (ix % 1000000 == 0) {

Thread.yield();

}

}

if (Thread.interrupted()) {

System.out.println("Interrupted, ending");

break;

}

}

}

}

Wed Jun 13 11:18:34 PDT 2007

main interrupting task

Interrupted, ending

Wed Jun 13 11:18:38 PDT 2007

main interrupting task

Interrupted, re-interrupting

Interrupted, ending

Wed Jun 13 11:18:41 PDT 2007

main interrupting task

Interrupted, ending

Wed Jun 13 11:18:44 PDT 2007

main interrupting task

Interrupted, ending

Wed Jun 13 11:18:47 PDT 2007

We can see that both the InterruptedException being caught and re-raising the flag by us calling interrupt() and the flag being raised by interrupt() being called when we're not blocking can be handled by checking interrupted() at the end of the loop.

jverda at 2007-7-12 19:14:34 > top of Java-index,Java Essentials,Java Programming...
# 15

> Exactly, the InterruptedException is the way the Java

> API uses to break out of its blocking methods. It

> won't be thrown in your face out of the blue.

I'm with jverd on this one... depending on an exception should not be your first choice. It makes for stinky code. Look how ugly the invocation below gets.

Granted, any interruption of a database operation would be an exceptional condition. There are instances in which you would want to do this, and handle interruption, so that you don't end up bogging down a server.

However, if the user presses cancel in a dialog box, I am not going to interrupt the thread that I was currently executing just to get in and make it stop.

public class ThreadInterruptTest {

class NiftyRunnable implements Runnable {

private int blah;

private boolean connectionReleased;

private boolean getConnectionReleased() {

return connectionReleased;

}

private synchronized void getDatabaseConnection() {

System.out.println("Getting database connection...");

connectionReleased = false;

}

private synchronized void releaseDatabaseConnection() {

System.out.println("Releasing database connection...");

connectionReleased = true;

}

public void run() {

getDatabaseConnection();

try {

while (blah < 100) {

System.out.printf("\b\b\b\b\b\b\b\b\b\bBlah. %3d%%", blah++);

Thread.sleep(10);

}

} catch (InterruptedException e) {

System.out.println("\n\nBlammo!");

} finally {

releaseDatabaseConnection();

}

}

}

public ThreadInterruptTest() {

NiftyRunnable myRunnable = new NiftyRunnable();

Thread theThread = new Thread(myRunnable);

theThread.start();

try {Thread.sleep(1000);} catch (InterruptedException e){/*gulp*/}

theThread.interrupt();

try {theThread.join();} catch (InterruptedException e) {/*gulp*/}

System.out.println("\n\nLet's see if the connection got released: " +

myRunnable.getConnectionReleased() );

}

public static void main(String[] args) {

new ThreadInterruptTest();

}

}

kevjavaa at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 16

> > Exactly, the InterruptedException is the way the

> Java

> > API uses to break out of its blocking methods. It

> > won't be thrown in your face out of the blue.

>

> I'm with jverd on this one... depending on an

> exception should not be your first choice.

I figured each approach had its uses, but my code above shows that simply using the interrupt mechanism can handle the general case.

I'm all for using the interrupt mechanism and forget the extra boolean that adds no capabilities anyway.

jverda at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 17

It is true that there are some cases in which you wouldn't want your API calls to be interrupted, such as a database operation. But as far as I know, these operations aren't interruptable according to the API documentation. Otherwise they would throw an InterruptionException just like Thread.sleep and Thread.join.

Here's a list of all the API calls which may throw InterruptedException:

http://java.sun.com/javase/6/docs/api/java/lang/class-use/InterruptedException.html

As for all IO operations, my earlier comment was misleading as it isn't the call of interrupt which makes them break out of a blocking call, but the closing of a stream or a socket.

Dalzhima at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 18

In case it wasn't clear, part of my point is that you're going to have to deal with the various interruption exceptions anyway.

You'll have to catch them and either swallow them or set your own flag. Ignoring them is the same either way, and setting your own flag is replaced by re-invoking interrupt(). At the end the loop, you just test interrupted() rather than testing your own flag.

In addition, if you want to treat interruptions of blocking methods specially, you can do it--and you can't do it without the exception.

jverda at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 19

> As for all IO operations, my earlier comment was

> misleading as it isn't the call of interrupt which

> makes them break out of a blocking call, but the

> closing of a stream or a socket.

Interesting. [url http://java.sun.com/j2se/1.5.0/docs/api/java/io/InterruptedIOException.html]InterruptedIOException[/url] says:

An InterruptedIOException is thrown to indicate that an input or output transfer has been terminated because the thread performing it was interrupted.

And this exception is thrown by plain old java.io classes.

But interrupt()'s docs sound like no exception will be thrown for I/O except for java.nio stuff.

Not totally clear to me...

Still, in the case of InterruptedIOException, it won't hurt to call interrupt(). The flag may be raised anyway, since this isn't InterruptedException, but it won't hurt to re-raise it.

jverda at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 20

This only occurs when you use the setSoTimeout function on a Socket so that you specify a maximum blocking delay on IO operations. The actual Exception being thrown is: [url=http://java.sun.com/j2se/1.5.0/docs/api/java/net/SocketTimeoutException.html]SocketTimeoutException[/url]

If you do not specify any socket timeout, you will never end up with an InterruptedIOException.

Since InterruptedIOException subclasses IOException instead of InterruptedException, I don't think the interrupted flag can be cleared, but it sure won't hurt to set it up again.

Dalzhima at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 21
> Since InterruptedIOException subclasses IOException> instead of InterruptedException, I don't think the> interrupted flag can be cleared, but it sure won't> hurt to set it up again.My point exactly. Thanks.
jverda at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 22
All right, I think I'm getting what you guys are saying, and it makes sense... so in all those APIs that throw the InterruptedException, the only graceful way to break out of it is to interrupt the thread.
kevjavaa at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 23

> All right, I think I'm getting what you guys are

> saying, and it makes sense... so in all those APIs

> that throw the InterruptedException, the only

> graceful way to break out of it is to interrupt

> the thread.

Not exactly. You could still just use your own flag instead, but you have to deal with InterruptedException anyway, and the interrupt mechanism also lets you do the same things you'd do with your own flag.

jverda at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 24

Well, as you probably noticed if you have read the list of methods which throw InterruptedException, the only methods throwing it are methods which put a Thread in a Waiting State for an infinite or a limited amount of time. When such Threads are waiting, the only way, graceful or not to break out of these waiting statements is to interrupt the Thread.

And jverd, you can't break out of a waiting API call with your own flag since they have no way of checking it out. You must use interrupt if you wish to bring a Thread in "Waiting" state out of its sleep.

Dalzhima at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 25
Interesting points raised. I learned this - if you want to break out RIGNT NOW!, use interrupt().But in any other case I don't see any advantage. And that would probably be most cases.~Bill
abillconsla at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 26

> limited amount of time. When such Threads are

> waiting, the only way, graceful or not to break out

> of these waiting statements is to interrupt the

> Thread.

I find C4 will end the wait, but it ain't graceful. :-)

> And jverd, you can't break out of a waiting API call

> with your own flag

Right. Didn't mean to imply that you could. I just meant that you could gracefully end a thread that makes these calls using your own flag--but only after that call returns of course. Sorry for not being clear.

jverda at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 27

> Interesting points raised. I learned this - if you

> want to break out RIGNT NOW!, use

> interrupt().

>

> But in any other case I don't see any advantage. And

> that would probably be most cases.

>

> ~Bill

Sarcasm is bad.. Don't make us re-explain all of this :P

> I find C4 will end the wait, but it ain't graceful.

> :-)

Or System.exit(0); ;)

> Right. Didn't mean to imply that you could. I just

> meant that you could gracefully end a thread that

> makes these calls using your own flag--but only after

> that call returns of course. Sorry for not being

> clear.

Just wanted to make sure ;)

Dalzhima at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 28

> Interesting points raised. I learned this - if you

> want to break out RIGNT NOW!, use

> interrupt().

>

> But in any other case I don't see any advantage. And

> that would probably be most cases.

1) If you call anything that can throw InterruptedException, you must deal with that exception anyway.

2) As pointed out earlier, by using interrupt(), you're using a standard method in the core API, no need to roll your own.

3) There's nothing you can do with your own flag that you can't do with interrupt, so there's no advantage to not using it.

jverda at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 29

"Sarcasm is bad.. Don't make us re-explain all of this :P"

Don't want you too. I really do believe I get it - it's more conforming you say, more in line with the way Sun does it, less clunky in your opinion, neater and cleaner.

But aside from the ability to break clean out without waiting for the loop to return I see no advantage.

abillconsla at 2007-7-21 22:16:36 > top of Java-index,Java Essentials,Java Programming...
# 30

Just a note to clariy.

If calling interrupt causes an exception to be thrown then the act of throwing the exception often clears the isInterrupted() flag.

If you are not blocked in a method that can throw an InterruptedException (such as wait, sleep etc.) then all you get is the isInterrupted flag being set.

" If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.

If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.

If none of the previous conditions hold then this thread's interrupt status will be set. "

cheers

Matfud

Message was edited by:

matfud

matfuda at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 31

> > Interesting points raised. I learned this - if you

> > want to break out RIGNT NOW!, use

> > interrupt().

> >

> > But in any other case I don't see any advantage.

> And

> > that would probably be most cases.

>

> 1) If you call anything that can throw

> InterruptedException, you must deal with that

> exception anyway.

>

> 2) As pointed out earlier, by using interrupt(),

> you're using a standard method in the core API, no

> need to roll your own.

>

> 3) There's nothing you can do with your own flag that

> you can't do with interrupt, so there's no advantage

> to not using it.

I appreciate the work you both put into this - but I really don't see eye to eye with you on it. To me it's 1/2 of 1 and 6dozen of the other ;o)

abillconsla at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 32

> > > Interesting points raised. I learned this - if

> you

> > > want to break out RIGNT NOW!, use

> > > interrupt().

> > >

> > > But in any other case I don't see any advantage.

> > And

> > > that would probably be most cases.

> >

> > 1) If you call anything that can throw

> > InterruptedException, you must deal with that

> > exception anyway.

> >

> > 2) As pointed out earlier, by using interrupt(),

> > you're using a standard method in the core API, no

> > need to roll your own.

> >

> > 3) There's nothing you can do with your own flag

> that

> > you can't do with interrupt, so there's no

> advantage

> > to not using it.

>

> I appreciate the work you both put into this - but I

> really don't see eye to eye with you on it. To me

> it's 1/2 of 1 and 6dozen of the other ;o)

There are some cases where using interrupt() is advantageous.

Can you give me a case where NOT using it is advantageous? What do you gain by using your own flag?

jverda at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 33

> > > > Interesting points raised. I learned this - if

> > you

> > > > want to break out RIGNT NOW!, use

> > > > interrupt().

> > > >

> > > > But in any other case I don't see any

> advantage.

> > > And

> > > > that would probably be most cases.

> > >

> > > 1) If you call anything that can throw

> > > InterruptedException, you must deal with that

> > > exception anyway.

> > >

> > > 2) As pointed out earlier, by using interrupt(),

> > > you're using a standard method in the core API,

> no

> > > need to roll your own.

> > >

> > > 3) There's nothing you can do with your own flag

> > that

> > > you can't do with interrupt, so there's no

> > advantage

> > > to not using it.

> >

> > I appreciate the work you both put into this - but

> I

> > really don't see eye to eye with you on it. To me

> > it's 1/2 of 1 and 6dozen of the other ;o)

>

>

> There are some cases where using interrupt() is

> advantageous.

>

really the only one I can see is where you want our NOW!

> Can you give me a case where NOT using it is

> advantageous? What do you gain by using your own flag?

No I can't and there probably aren't any either. But that's in itself is not enough for me to want to change.

Ah ... maybe I'll try it next time and see if I like it better. Thanks for the discussion at any rate - always good to take it in.

abillconsla at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 34
My point was that if they're equal sometimes, and one is advantageous occasionally, why not just stanardize on that one?But I accept your point--you're used to one way, and it works, and you have no reason to change.
jverda at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 35

What I meant by sarcasm is bad is that I really thought you were sarcastic...

as I said earlier, calling interrupt on a Thread instance doesn't make it stop immediately. It just raises a flag indicating it has been interrupted (and this flag should always be checked by any Thread which runs in a nearly infinite loop) and if the Thread was currently blocked inside an API call which may throw InterruptedException, then it will do so and break out of the blocking.

And thanks matfud for your interesting clarifications on InterruptableChannels and Selectors :)

Dalzhima at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 36

> What I meant by sarcasm is bad is that I really

> thought you were sarcastic...

>

No problem - saw the :P dude face and figured you were just egging me.

> as I said earlier, calling interrupt on a Thread

> instance doesn't make it stop immediately. It just

> raises a flag indicating it has been interrupted (and

> this flag should always be checked by any Thread

> which runs in a nearly infinite loop) and if the

> Thread was currently blocked inside an API call which

> may throw InterruptedException, then it will do so

> and break out of the blocking.

>

> And thanks matfud for your interesting clarifications

> on InterruptableChannels and Selectors :)

Yes I too liked that summnation - though it was a bit complicated.

abillconsla at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 37

> > I appreciate the work you both put into this - but

> I

> > really don't see eye to eye with you on it. To me

> > it's 1/2 of 1 and 6dozen of the other ;o)

>

>

> There are some cases where using interrupt() is

> advantageous.

>

> Can you give me a case where NOT using it is

> advantageous? What do you gain by using your own flag?

Use whichever makes your code clearer.

A question I'd like to ask is

"do methods like wait/sleep/etc test the isInterrupted status on entry? I don't have acess to the source at the moment"

If they do then that could be a good reason not to recall interupt() in a loop that you wish to terminate normally.

Cheers

matfud

matfuda at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 38

But if there really is one thing that should convince you to use the interrupted flag rather than a custom one, it is the fact that you can implement generic code to handle Threads and be able to make them stop as soon as possible using the interrupt instance method without knowing any implementation details.

Where is the logic when you call "stop" on a Runnable object when what you really want to stop is the Thread? ;)

Dalzhima at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 39
> And thanks matfud for your interesting clarifications> on InterruptableChannels and Selectors :)Much as I'd like to take credit. Most of that is a direct copy from the java docs :)matud
matfuda at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 40

> But if there really is one thing that should convince

> you to use the interrupted flag rather than a custom

> one, it is the fact that you can implement generic

> code to handle Threads and be able to make them stop

> as soon as possible using the interrupt instance

> method without knowing any implementation details.

>

Don't get me started on Generics - bloody awful contrapturous(sic) medling language sinking trash addon tacky bit of ruffled plummage ought to put out to pasture and shot ... rrrrrrrrr :oP

> Where is the logic when you call "stop" on a Runnable

> object when what you really want to stop is the

> Thread? ;)

It's logical if for no other reason than - if you can get used to Generics and after a while like 'em , then you should oughta be able to get used to a simple STOP method (you can always call it "stopOnlyTheThreadInThisRunnable()" if that makes it any easier BTW - since that's the way we've been doing it since about - well whenever they deprecated stop().

But like jverd says ... and I second ... I can understand if that's what you're used to ... ;o)

abillconsla at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 41

> Where is the logic when you call "stop" on a Runnable

> object when what you really want to stop is the

> Thread? ;)

It can't be done safely and performantly.

I suppose it might be possible to have stop() wait for a piece of code to release all locks it holds before terminating it but code might never release all its locks.

Forcing code to release locks means the data structures are in an indeterminate state. This may be OK in many situations if you are willing to throw that data away when you call stop. However it tends to just cause problems. (I would love a way to do it though)

Cheers

matfud

matfuda at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 42
I just tested setting the Interrupt status before calling Thread.sleep() and as expected, I received an InterruptedException right when I called Thread.sleep(). Thus re-setting the interrupt status will make it possible for the loop to stop.
Dalzhima at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 43

> I just tested setting the Interrupt status before

> calling Thread.sleep() and as expected, I received an

> InterruptedException right when I called

> Thread.sleep(). Thus re-setting the interrupt status

> will make it possible for the loop to stop.

Glad someone could test it.

Actually I ment that catching InterupptedException and then rethrowing it could cause the rest of your loop (that you are trying to finish before teminating) to bahave differently as subsequent calls to wait/sleep/notify/notifyAll/yeild and possibly some of the (non)blocking IO methods may now behave differently.

If so you might want to NOT recall interrupted.

Cheers

matfud

matfuda at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 44

When I said generic code, I didn't mean code which uses generics, but code which will work with any Thread object. Just like implementing the Runnable interface allows for much more flexibility than extending the Thread class, using the interrupt flag rather than a custom one will make it much easier for various pieces of software to tie up together.

A good example of how your Threaded code would tie up better with other pieces of software by using the interrupt flag is if you ever start using ThreadPools. The Java API already offers ThreadPools under the name of ExecutorService. These offer the functionality of canceling tasks which are currently being executed and it relies on the interrupted flag to cancel such tasks.

As for the InterruptedException matfud, we never meant to rethrow it! What we are saying is that since catching an InterruptedException clears the interrupted flag, it is important to call Thread.currentThread().interrupt() once again to set the flag if our catch clause was inside the loop which check for the interrupted flag. There are many ways to handle an InterruptedException and everything depends on the context.

Dalzhima at 2007-7-21 22:16:45 > top of Java-index,Java Essentials,Java Programming...
# 45

sorry I wasn't clear. I mean recalling the interrupt() method when you catch one. It may cause problems later in your loop if you need other methods that automatically rethrow the InterruptedException if the flag is set to complete your loop without putting your data into an inconsitant state.

I'm fairly sure this is pretty uncommon but it could be a reason why you dont want to recall the interrupted() method.

matfud

matfuda at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 46
Okay I understand your point now. In this kind of situation, it is true that a loop would need to rely on both the interrupted flag and an internal flag. But again there shouldn't be any method which raises that internal flag. Calling interrupt should always be the solution.
Dalzhima at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 47

> When I said generic code, I didn't mean code which

> uses generics, but code which will work with any

> Thread object. Just like implementing the Runnable

> interface allows for much more flexibility than

> extending the Thread class, using the interrupt flag

> rather than a custom one will make it much easier for

> various pieces of software to tie up together.

>

Oh ... well, er, a, anyway never want to miss an opportunity to rant about Generics ... I hope I'll be able to get used to them BTW - at first I hated vi, now I like it ...

> A good example of how your Threaded code would tie up

> better with other pieces of software by using the

> interrupt flag is if you ever start using

> ThreadPools. The Java API already offers ThreadPools

> under the name of ExecutorService. These offer the

> functionality of canceling tasks which are currently

> being executed and it relies on the interrupted flag

> to cancel such tasks.

>

This reminds me of the old COBOL debate about nested IFs versus individual IF statements ... that one used to get alot of wear. It really comes down though to no two people's brain being wired exactly alike ... you say tuh-mey-toh, -mah, I say tuh-mah-toh, -mah ...

Notwithstanding what I said before - interesting stuff, enjoyed listening and respect your point of view.

>

> As for the InterruptedException matfud, we never

> meant to rethrow it! What we are saying is that

> since catching an InterruptedException clears the

> interrupted flag, it is important to call

> Thread.currentThread().interrupt() once again to set

> the flag if our catch clause was inside the loop

> which check for the interrupted flag. There are many

> ways to handle an InterruptedException and everything

> depends on the context.

abillconsla at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 48

Well, I don't consider this as being only a point of view ;) If you want to be able to use all of the API's constructs, you have to keep up to it's standards. If your threads do not use the interrupt flag, then you'll never be able to use the cancel feature of the ThreadPool API. That's why I was talking about flexibility :) By using your own custom flag, you cut yourself from many tools which use the "sun standard" ;)

Dalzhima at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 49
What's the difference between a ThreadGroup and a ThreadPool?
abillconsla at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 50
A ThreadGroup represents a hierarchy of Threads.A ThreadPool is a Collection of Threads which are created once and which will execute asynchronous Tasks which are being queued.
Dalzhima at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 51

> Okay I understand your point now. In this kind of

> situation, it is true that a loop would need to rely

> on both the interrupted flag and an internal flag.

> But again there shouldn't be any method which raises

> that internal flag. Calling interrupt should always

> be the solution.

Catchin an InterruptedException and then calling Thread.currentTread().interrupt() does reraise the flag.

Whether it should do or not is not really the issue. It does.

So there is no "one way" to write loops. It depends on what you want. (Sorry I was writing code today and had this issue. I solved the problem by making the Runnable into a TimedTask instance. This means that the run() method always has to exit. it was a good solution for me as this task needs to run periodically. Still have to handle InterruptedExceptions but no need for additional testing of isInterrupted or a custom variable.

matfud

matfuda at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 52
Thanks, guys, I really appreciate the debate, and you can consider me among the begrudgingly converted :). Threads like this (forum threads, I mean) are why I hang around this place so often when I should really be working. Cheers,kev
kevjavaa at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 53
I agree with you kevjava, this is the kind of Thread which allows for learning a lot of nice nitpicky details ;) I wish I could have more of these with my coworkers...
Dalzhima at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 54

Yes I asked because I noticed in Josh B's book that he recommends avoiding ThreadGroups, and I remembered reading/hearing about ThreadPools here and there and as soon as I asked I started looking it all up.

ThreadGroups go way back and such.

ThreadPools though ... I confess I have never had the need to use. Quick lookup shows ThreadPoolExecutor ... in java.util.concurrent ... don't see any class or interface ThreadPool - is this in EE?

abillconsla at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 55
Nope, ThreadPool is the concept, but Java called it ExecutorService.take a look at:java.util.concurrent.Executorsjava.util.concurrent.ExecutorServiceIt is available since Java 1.5
Dalzhima at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 56
Ok ... I was in the right package. Yeah, I probably won't have any use for these in the near future. But thanks again for bringing it to my attention.
abillconsla at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 57
> Actually I ment that catching InterupptedException> and then rethrowing itThat has not come up as an option to my knowledge, nor could I imagine why you'd want to do it.
jverda at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 58

> sorry I wasn't clear. I mean recalling the

> interrupt() method when you catch one. It may cause

> problems later in your loop if you need other methods

> that automatically rethrow the InterruptedException

> if the flag is set to complete your loop without

> putting your data into an inconsitant state.

>

Eh? I don't see that happening.

If a method can throw it, catch it and call interrupted(). Then, at one or more points in your loop--wherever it's appropriate, just check isInterrupted().

jverda at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 59

>

> Eh? I don't see that happening.

>

> If a method can throw it, catch it and call

> interrupted(). Then, at one or more points in your

> loop--wherever it's appropriate, just check

> isInterrupted().

If your thread is running a loop that needs to exit cleanly, then an interruptException could be thrown in a wait() (for example). If it is and you handle it by calling Thread.currentThread.interrupt() then it may make any subsequent calls to wait/sleep/BlockingIO, that need to occur before your loop terminates correctly, behave differently then if you set a separate "teminate" variable.

If the isInteruppted flag is set these methods behave differently.

As I said its probably an unusual situation but not without precident.

matfud

matfuda at 2007-7-21 22:16:50 > top of Java-index,Java Essentials,Java Programming...
# 60
I see. Maybe. :-)I think I'd have to see it if/when it happened. I'll go with interrupt() because I think it's simpler (no extra variable with synced get/set), and then deal with this situation if/when it arises.
jverda at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 61
I agree, it is much simpler. I was just trying to figure out if there was any potential downside to using it all the time.Conclusion: Possibly.matfud
matfuda at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 62
Thanks everyone. Kev, I apologize for being snappy. I'm just a cocky, 21-year-old, kid from Boston. I'm a **** to plenty of people. Nothing personal. > =)
kwiknessa at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 63

So.... in my stop() method, i'm using interrupt().

private void stop()

{

if (thread != null)

{

thread.interrupt();

thread = null;

//System.out.println("Stopping thread");

}

}

So if i'm interrupting this baby, why am I getting InterruptedExceptions for calling sleep? I think what I really need to do is learn to use the java debugger..

I used the threads command before the InterruptedException is thrown in the jdk command line debugger and got the following output:

C:\Documents and Settings\Owner\Desktop\MyBlackjackGame>jdb Main

Initializing jdb ...

> stop in BlackjackPanel$CardPanel.run

Deferring breakpoint BlackjackPanel$CardPanel.run.

It will be set after the class is loaded.

> run

run Main

Set uncaught java.lang.Throwable

Set deferred uncaught java.lang.Throwable

>

VM Started: Set deferred breakpoint BlackjackPanel$CardPanel.run

Breakpoint hit: "thread=Thread-2", BlackjackPanel$CardPanel.run(), line=453 bci=

0

453 if (doDealAnimation)

Thread-2[1] cont

> player's cards:

#1 2 Diamonds

#2 2 Diamonds

dealer's cards:

#1 2 Diamonds

#2 2 Diamonds

player's cards:

#1 2 Diamonds

#2 2 Diamonds

dealer's cards:

#1 2 Diamonds

#2 2 Diamonds

Breakpoint hit: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=453 bci=

0

453 if (doDealAnimation)

Thread-3[1] next

>

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=462 bci=

32

462 else if (doHitAnimation)

Thread-3[1] next

>

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=464 bci=

39

464if (playerToAnimate == "player")

Thread-3[1] next

>

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=500 bci=

243

500else if (playerToAnimate == "dealer")

Thread-3[1] next

>

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=503 bci=

252

503 animateHit(dealer, (dealer.hand.size() -

1));

Thread-3[1] next

> dealer's cards:

#1 2 Diamonds

#2 2 Diamonds

#3 2 Diamonds

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=505 bci=

278

505 if (dealer.getPointTotal() > 21)

Thread-3[1] next

>

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=528 bci=

389

528 if (stayHasBeenClicked)

Thread-3[1] next

>

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=530 bci=

396

530 if (dealer.getPointTotal() < 17)

Thread-3[1] next

>

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=532 bci=

411

532bp.doStay();

Thread-3[1] next

>

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=533 bci=

421

533stop();

Thread-3[1] next

>

Step completed: "thread=Thread-3", BlackjackPanel$CardPanel.run(), line=534 bci=

425

534return;

Thread-3[1] next

>

Breakpoint hit: "thread=Thread-4", BlackjackPanel$CardPanel.run(), line=453 bci=

0

453 if (doDealAnimation)

Thread-4[1] next

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.run(), line=462 bci=

32

462 else if (doHitAnimation)

Thread-4[1] next

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.run(), line=464 bci=

39

464if (playerToAnimate == "player")

Thread-4[1] next

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.run(), line=500 bci=

243

500else if (playerToAnimate == "dealer")

Thread-4[1] next

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.run(), line=503 bci=

252

503 animateHit(dealer, (dealer.hand.size() -

1));

Thread-4[1] step

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

17 bci=0

717if (p.getPlayerOrDealer() == "player")

Thread-4[1] step

>

Step completed: "thread=Thread-4", Player.getPlayerOrDealer(), line=18 bci=0

18 return playerOrDealer;

Thread-4[1] step

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

17 bci=4

717if (p.getPlayerOrDealer() == "player")

Thread-4[1] step

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

46 bci=149

746if (p.getPlayerOrDealer() == "dealer")

Thread-4[1] step

>

Step completed: "thread=Thread-4", Player.getPlayerOrDealer(), line=18 bci=0

18 return playerOrDealer;

Thread-4[1] step

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

46 bci=153

746if (p.getPlayerOrDealer() == "dealer")

Thread-4[1] step

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

50 bci=158

750 if(handIndex == 0)

Thread-4[1] step

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

53 bci=181

753animationCard = p.hand.g

et(handIndex).getGraphic();

Thread-4[1] step

>

Step completed: "thread=Thread-4", Card.getGraphic(), line=65 bci=0

65 return graphic;

Thread-4[1] next

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

53 bci=196

753animationCard = p.hand.g

et(handIndex).getGraphic();

Thread-4[1] next

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

55 bci=199

755 while (animY != 10)

Thread-4[1] next

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

57 bci=208

757animY -= 2;

Thread-4[1] next

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

58 bci=218

758Thread.sleep(3);

Thread-4[1] threads

Group system:

(java.lang.ref.Reference$ReferenceHandler)0x110 Reference Handler cond. waitin

g

(java.lang.ref.Finalizer$FinalizerThread)0x10f Finalizer cond. waitin

g

(java.lang.Thread)0x10e Signal Dispatcher running

Group main:

(java.lang.Thread)0x218 Java2D Disposercond. waitin

g

(java.lang.Thread)0x239 AWT-Shutdowncond. waitin

g

(java.lang.Thread)0x23a AWT-Windowsrunning

(java.awt.EventDispatchThread)0x371 AWT-EventQueue-0 cond. waitin

g

(java.lang.Thread)0x423 DestroyJavaVMrunning

(java.lang.Thread)0x432 Thread-4 running

Thread-4[1] next

>

Step completed: "thread=Thread-4", BlackjackPanel$CardPanel.animateHit(), line=7

87 bci=325

787 }catch(InterruptedException ie)

Thread-4[1] next

Step completed: Thread-4[1] "thread=Thread-4", BlackjackPanel$CardPanel.animateH

it(), line=789 bci=326

789System.exit(0);

Thread-4[1] next

>

The application exited

C:\Documents and Settings\Owner\Desktop\MyBlackjackGame>

Can anyone tell which thread is being interrupted by sleep() by looking at this? Help me Obi-Wan-Kenobi, you're my only hope. (*KSSSHHHHT!*)

kwiknessa at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 64

> So.... in my stop() method, i'm using interrupt().

> ...

> So if i'm interrupting this baby, why am I getting

> InterruptedExceptions for calling sleep?

... because that is precisely what is supposed to happen. Or would you rather the thread not be interrupted?

ejpa at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 65
> Kev, I apologize for being snappy.No harm no foul, it's all good.
kevjavaa at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 66
You showed us that much of the debug trace without showing us the actual code being debugged!?
Dalzhima at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 67

> Thanks everyone.

>

> Kev, I apologize for being snappy. I'm just a cocky,

> 21-year-old, kid from Boston. I'm a **** to plenty of

> people. Nothing personal.

>

> > =)

I think I understand what you mean (figure of speech on your part and all) and this is not meant as a criticism, but keep in mind that @21, you're not a "kid" anymore.

abillconsla at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 68
**** are you serious? I thought I was a kid too!
Dalzhima at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 69
> **** are you serious? I thought I was a kid too!So should I presume you're over 20?
abillconsla at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 70
Such presumptions would be accurate. ^_^
Dalzhima at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 71
>You showed us that much of the debug trace without showing us the actual code being debugged!?\On my first post, there's a link to d/l the source for my app.
kwiknessa at 2007-7-21 22:16:55 > top of Java-index,Java Essentials,Java Programming...
# 72

>... because that is precisely what is supposed to happen. Or would you rather the thread not be interrupted?

Yes. I want sleep() to run without throwing an exception at all. I thought that was the correct way of doing it.. I thought that if I merely swallowed it, it would cause some crazy glitches or something. I dunno. Hopefully someone will take a peek at my code.

In the program, i've set all the cards to 2 of Diamonds. I did this so that the bug occurs every time the "Stay" button is clicked.

kwiknessa at 2007-7-21 22:16:56 > top of Java-index,Java Essentials,Java Programming...
# 73

I don't - I really really really don't ;o) - want to re-open this entire discussion ... but it sounds like you might want to consider doing this the old fashioned way, as per the code kev and I posted on page one of this thread. Either that or check that interrupt internal flag as the other folks mentioned.

abillconsla at 2007-7-21 22:16:56 > top of Java-index,Java Essentials,Java Programming...
# 74

If you don't want to interrupt your sleep, there's an easy way...

public void uninterruptableSleep(long sleepTime) {

long startTime;

while(sleepTime > 0) {

try {

startTime = System.currentTimeMillis()

Thread.sleep(sleepTime);

} catch(InterruptedException e) {

} finally {

sleepTime -= (System.currentTimeMillis() - startTime);

}

}

}

Dalzhima at 2007-7-21 22:16:56 > top of Java-index,Java Essentials,Java Programming...