Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interrupt / Kill a running thread

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.

like image 254
nija Avatar asked Dec 23 '11 11:12

nija


3 Answers

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:

  • Have a volatile boolean flag that the thread's Runnable checks from time to see if it should stop (the same flag that could be used as a condition in a thread loop).
  • Call 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.
like image 106
Guillaume Avatar answered Oct 21 '22 09:10

Guillaume


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.

like image 23
A.H. Avatar answered Oct 21 '22 09:10

A.H.


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
}
like image 26
bragboy Avatar answered Oct 21 '22 07:10

bragboy