2

After reading several SO posts on how to kill a Java thread, I fairly understand why stop is unsafe and how to handle the graceful stop.

But the solutions are targeting towards UI threads where repainting is the problem and not really a long running - blocking process executed by a thread.

Links:

How do you kill a Thread in Java? https://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

One precise point that I fail to understand from the solutions or examples is what is the long-running-part the samples are trying to simulate.

Eg: In this following code, what if I set the interval to INT.MAX.

public void run() {
        Thread thisThread = Thread.currentThread();
        while (blinker == thisThread) {
            try {
                thisThread.sleep(interval);  // This might take forever to complete, 
                                             // and while may never be executed 2nd time.

                synchronized(this) {
                    while (threadSuspended && blinker==thisThread)
                        wait();
                }
            } catch (InterruptedException e){
            }
            repaint();
        }
    }

    public synchronized void stop() {
        blinker = null;
        notify();
    }

The reason am asking for this use case is that, I have a bug in a legacy code base that runs another executable in a Thread. Now the ask if the user wishes to stop the thread, we would need to kill this thread, and the executable which is part of this thread automatically gets killed.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Raghav
  • 2,890
  • 7
  • 36
  • 56

1 Answers1

4

The way you stop a thread is by asking it - nicely - to stop. It's up to the code the thread is running to listen for and act on that request.

Specifically, the way you do it is to interrupt the thread. Your code checks for the interruption - Thread.sleep and Object.wait will throw InterruptedException if the thread is interrupted before or during their execution; but you catch the interruption, and ignore it, so you won't act on it.

Instead of this:

while (condition) {
  try {
    Thread.sleep(...);

    wait();
  } catch (InterruptedException e) {
  }
}

Put the interruption outside the loop:

try {
  while (condition) {
    Thread.sleep(...);
    wait();
  }
} catch (InterruptedException e) {
}

then the loop terminates if it is interrupted.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • In place of Thread.Sleep, if there is a synchronous API call, with timeout set to 1 hour, can this operation be still interrupted ? – Raghav May 18 '20 at 19:22
  • That API call has to listen for and act on the interruption, in exactly the same way that `Thread.sleep` does. – Andy Turner May 18 '20 at 19:23
  • Thanks Andy.... In my case, the task or process that is invoked (long running method from thread's run), doesn't have the listen-to-interrupt or cancel logic. While I am open to move the code from thread to Executor, few folks in my team feels that the thread can still be interrupted from outside its run-scope. Or, I understood them wrong... – Raghav May 18 '20 at 19:27
  • Executing the code in an executor doesn't make it magically cancellable. All you can do is request the cancellation. Having something that you expect to take an hour, and not having it cancellable, is just a terrible idea. – Andy Turner May 18 '20 at 19:33
  • 2
    @Raghav If the code provides no way to cancel it, then it can't be canceled. If you can't modify the code, you either have to let it run or put it in its own process and terminate that process. Supporting clean cancellation is complex and can't be forced into code without designing it into that code. – David Schwartz May 18 '20 at 19:34