Does Thread.stop() really stop a Thread?

Overview

Thread.stop() is deprecated, with good reason. However there are times when it is really the only option available to you.

How does Thread.stop() really work

Thread.stop() creates a java.lang.ThreadDeath which is an Error. It uses the current threads stack trace and causes the thread you use to throw this error.

However, at this point, its an Error like any other. You can catch it, print it and ignore it. Any finally block will be called as normal and any synchronized blocks will be unlocked in the same manner as throwing this Error in the current thread.

What is special about ThreadDeath

Apart from its name not ending in Error, ThreadDeath is unusual in that it is not printed by default if not caught. The ThreadGroup.uncaughtException() method ignores this exception by default. You can change this behaviour by overriding this method or using Thread.setDefaultUncaughtExceptionHandler();

Note: if you do print the stack trace of ThreadDeath, it has the stack trace of the thread which created it, not the place where the Thread stopped.

An example

Thread t = new Thread() {
    @Override
    public void run() {
        try {
            System.out.println("Thread start");
            Thread.sleep(1000);
            System.out.println("Thread end");
        } catch (InterruptedException ie) {
            System.out.println("Thread Interrupted");
        } catch (Error e) {
            System.out.println("Thread threw an error " + e);
            throw e;
        } finally {
            System.out.println("Thread finally");
        }
    }
};
t.start();
t.join(100);
t.stop();
prints
Thread start
Thread threw an error java.lang.ThreadDeath
Thread finally

You can see that finally is called and I have to re-throw the error for it to continue unwinding the stack. If I was to catch and discard it, my thread continue on as normal.

BTW: A sub-class of ThreadDeath will not be printed by default as well.

Why is Thread.stop() unsafe

You have no control over where in the code the thread is "stopped" or what operations it might be performing. This can leave shared resources in an inconsistent state. It can work you you 99 times and fail the next time.

You have to consider what the thread is doing and what could happen if it is stopped on any line.

What is the alternative?

The best alternative is to make your thread interruptable. This can be as simple as adding the following line at key points in your code.
if (thread.interrupt()) throw new InterruptedException();

The thread trying to stop the interruptable thread can call Thread.interrupt() or Future.cancel(true); This has the advantage of only breaking the thread at safe points.

Another use for Thread.stop()

There is an overloaded version of method Thread.stop(Throwable). This allows you to cause any Throwable to be thrown. It is no more safe that the other method except when you use to cause the current thread to throw a Throwable. This is because you know the exact line it is being thrown and you can determine if this is a valid thing to do.

try {
   // throws a few checked exceptions
} catch (Exception e) {
   // log the exception or process it.

   // re-throw the original exception without the compiler complaining.
   Thread.currentThread().stop(e); 
}

Summary

Thread.stop() doesn't cause a Thread to stop, but it does cause it to throw an error. This ThreadDeath Error is likely to be uncaught and won't be printed by default giving the appearance of stopping your thread.

Comments

  1. Nice post, thanks ! +1 on dzone

    ReplyDelete
  2. Good post mate. Even though Java's Thread and Concurrency API is quite reach it doesn't provide any safe method to stop a Thread or reuse a Thread directly. Though Executor framework some what handles this by using worker thread but in many scenario a direct control is needed. By the way here is mine way of Stopping Thread in Java

    ReplyDelete
  3. I used Thread.stop();
    Now .stop(); is deprecated.
    How to Stop/Kill Thread?

    ReplyDelete
    Replies
    1. Thread.stop() is disabled in Java 8. You need to ensure your threads can stopped gracefully, or run them in a separate process you can kill.

      Delete

Post a Comment

Popular posts from this blog

Low Latency Microservices, A Retrospective

Unusual Java: StackTrace Extends Throwable

System wide unique nanosecond timestamps