Li' Li' - 6 months ago 14
Java Question

How to find and stop all currently running threads?

I have an multiple-threaded java project and I want to add a method stop() to stop all the running threads. The problem is that this project is developed by someone else, and I am not familiar with how it implements multiple threads.

What I know is that once the project get started, many threads are invoked and they run forever. Is there a way to find all running threads and stop them? I have searched a lot, and found how to get a list of running threads:

Set<Thread> threadSet = Thread.getAllStackTraces().keySet();


What to do next to stop all the running threads?

The reason why I want to stop these threads is that I need to deploy this project to OSGi container as a bundle. Once the bundle is started, multiple threads run forever. So I need to implement a destroy() method to stop all threads to control the bundle lifecycle.

How about

for (Thread t : Thread.getAllStackTraces().keySet())
{ if (t.getState()==Thread.State.RUNNABLE)
t.interrupt();
}

for (Thread t : Thread.getAllStackTraces().keySet())
{ if (t.getState()==Thread.State.RUNNABLE)
t.stop();
}

Answer

This is a dangerous idea. The Javadocs for Thread.stop() explain:

This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait.

Fundamentally, threads need to be built and designed to safely terminate, it is not possible to safely kill arbitrary threads. A fairly standard pattern is implemented like so:

public abstract class StoppableRunnable implements Runnable {
    private volatile boolean stopWork;;
    private boolean done;

    public final void run() {
        setup();
        while(!stopWork && !done) {
            doUnitOfWork();
        }
        cleanup();
    }

    /**
     * Safely instructs this thread to stop working,
     * letting it finish it's current unit of work,
     * then doing any necessary cleanup and terminating
     * the thread.  Notice that this does not guarentee
     * the thread will stop, as doUnitOfWork() could
     * block if not properly implemented.
     */
    public void stop() {
        stopWork = true;
    }

    protected void done() {
        done = true;
    }

    protected void setup() { }
    protected void cleanup() { }

    /**
     * Does as small a unit of work as can be defined
     * for this thread.  Once there is no more work to
     * be done, done() should be called.
     */
    protected abstract void doUnitOfWork();
}

You implied you aren't the author of these threads, which suggest they may not be safely stoppable. In such a case, you can call Thread.interrupt() to instruct the thread to stop what it's doing (instead of the pattern described above, you could use Thread.interrupt() to similar effect) however similarly, if the thread's designer hasn't written it to handle interrupts, this may not do anything or cause inconsistent states or other errors.

Ultimately, Thread.stop() is what you want if you just want to "[Force] the thread to stop executing" and can't modify the thread's implementation; however like using kill in Unix, this is a dangerous proposition, and you should essentially consider your JVM to be in an unstable and irreparable state after terminating a thread in this way, and attempt to exit the program as quickly as possible thereafter.


Regarding your suggestion of interrupting then stopping:

There's still a lot of problems here, in particular, interrupting does not guarantee the thread will interrupt immediately (it works similarly, though less explicitly, to my StoppableRunnable above) and instead sets a flag that the thread should interrupt when possible. This means you could call Thread.interrupt(), the thread could start it's proper interrupt-handling behavior, then midway through that, your call to Thread.stop() fires, violently killing the thread and potentially breaking your JVM. Calls to Thread.interrupt() provide no guarantee as to when or how the thread will respond to that interrupt, which is why I prefer the explicit behavior in StoppableRunnable. Needless to say, if you're ever going to call Thread.stop() there's little to be gained by calling Thread.interrupt() first. I don't recommend it, but you might as well just call Thread.stop() in the first place.

Additionally, recognize that the code running your loop is itself in a thread - meaning your loop could very well kill itself first, leaving all other threads running.