On occurrence of a specific timeout, I need to kill/cancel/interrupt/fail a running thread. I use ExecutorService to manage a pool of threads, through which I am able to cancel the task using the Future's cancel() method which removes this from the ExecutorService's view, but the thread itself continues to run.
Looking around online, people talk about interrupting threads that have a loop using the isInterrupted() method or are waiting on IO which can be handled by surfacing InterruptedException.
What is the general practice on killing threads that neither loop (or have any other hooks) and are not waiting on IO? Looking around, Thread.stop() seems to do what I need (just blindly kill the thread) but it is not recommended to be used.
If you use an ExecutorService
then you should not mess with its threads: this notion is hidden behind the executor which is a higher-level notion than threads and thus does not provide methods to manage them. I strongly advise you to stop the whole Executor and not try to stop one of its threads.
Please note the threads in an ExecutorService
are looping, their loop includes waiting for a task to be available in their tasks queue.
There is no simple mean in Java to stop a thread that is not looping, what you can do is:
Runnable
checks from time to see if it should stop (the same flag that could be used as a condition in a thread loop).Thread.interrupt()
to try (best effort, quite unsafe if you do not know what you are doing) stop a synchronization-related wait/lock/aquire/... the thread is stuck in.If you alread have an Executorservice
then you have received a Future
already. The only sane and and clean way to cancel the job is therefore calling future.cancel(boolean mayInterruptIfRunning)
. Setting mayInterruptIfRunning
will interrupt the jobs if it currently running and does nothing if the job is not running. So you only have to write the job in a way to honour the interruption by checking Thread.interrupted()
every now and then.
Please note the difference between a job and a thread. You submit a job and therefore you should not muck with a thread by trying to circumvent the ExecutorService
which might be not amused at all about that. Calling Future.cancel(true)
you give all involved parties a clean signal what to do.
I would personally recommend you to go for the interrupting route since it is the cleanest way and the graceful way to end that thread.
Lets try to well define our objective. A thread is nothing but a separate process going to do a set of tasks that you assign it to do. Probably you will have to find the interruptable points in your code and have to do an interrupted() check at these points. Obviously these points should have reached a logical ending.
For example,
public void run(){
if (Thread.currentThread().interrupted()) {
return;
}
//LogicA start
//LogicA end
if (Thread.currentThread().interrupted()) {
return;
}
//LogicB start
//LogicB end
if (Thread.currentThread().interrupted()) {
return;
}
//LogicLong start
//Long code here cannot end or exit or kill the thread now. Let it finish
//LogicLong ends
if (Thread.currentThread().interrupted()) {
return;
}
//LogicD start
//LogicD end
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With