Stopping thread Immediately
Thread.interrupt
will not stop your thread (unless it is in the sleep, in which case the InterruptedException
will be thrown). Interrupting basically sends a message to the thread indicating it has been interrupted but it doesn't cause a thread to stop immediately.
When you have long looping operations, using a flag to check if the thread has been cancelled is a standard approach. Your methodA
can be modified to add that flag, so something like:
// this is a new instance variable in `A`
private volatile boolean cancelled = false;
// this is part of your methodA
for (int n=0;n<100;n++) {
if ( cancelled ) {
return; // or handle this however you want
}
}
// each of your other loops should work the same way
Then a cancel method can be added to set that flag
public void cancel() {
cancelled = true;
}
Then if someone calls runEverything
on B
, B
can then just call cancel
on A
(you will have to extract the A
variable so B
has a reference to it even after runEverything
is called.
I think you should persevere with using Thread.interrupt()
. But what you need to do to make it work is to change the methodA
code to do something like this:
public void methodA() throws InterruptedException {
for (int n=0; n < 100; n++) {
if (Thread.interrupted) {
throw new InterruptedException();
}
//Do something recursive
}
// and so on.
}
This is equivalent declaring and using your own "kill switch" variable, except that:
- many synchronization APIs, and some I/O APIs pay attention to the
interrupted
state, and - a well-behaved 3rd-party library will pay attention to the
interrupted
state.
Now it is true that a lot of code out there mishandles InterruptedException
; e.g. by squashing it. (The correct way to deal with an InterruptedException
is to either to allow it to propagate, or call Thread.interrupt()
to set the flag again.) However, the flip side is that that same code would not be aware of your kill switch. So you've got a problem either way.