How to Stop a Java Thread Gracefully

How to stop a java thread gracefully?

The good way to do it is to have the run() of the Thread guarded by a boolean variable and set it to true from the outside when you want to stop it, something like:

class MyThread extends Thread
{
volatile boolean finished = false;

public void stopMe()
{
finished = true;
}

public void run()
{
while (!finished)
{
//do dirty work
}
}
}

Once upon a time a stop() method existed but as the documentation states

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.

That's why you should have a guard..

is this the correct way to 'stop' a thread gracefully?

Use Thread.interrupt() method instead of Thread.stop(). In the interrupted thread you can catch the InterruptedException and do any cleanup required.

A similar questions has already been asked here, you can find a code sample there too.

How to properly stop the Thread in Java?

In the IndexProcessor class you need a way of setting a flag which informs the thread that it will need to terminate, similar to the variable run that you have used just in the class scope.

When you wish to stop the thread, you set this flag and call join() on the thread and wait for it to finish.

Make sure that the flag is thread safe by using a volatile variable or by using getter and setter methods which are synchronised with the variable being used as the flag.

public class IndexProcessor implements Runnable {

private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private volatile boolean running = true;

public void terminate() {
running = false;
}

@Override
public void run() {
while (running) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);

LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
running = false;
}
}

}
}

Then in SearchEngineContextListener:

public class SearchEngineContextListener implements ServletContextListener {

private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);

private Thread thread = null;
private IndexProcessor runnable = null;

@Override
public void contextInitialized(ServletContextEvent event) {
runnable = new IndexProcessor();
thread = new Thread(runnable);
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}

@Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (thread != null) {
runnable.terminate();
thread.join();
LOGGER.debug("Thread successfully stopped.");
}
}
}

How to gracefully stop a thread that is running a blocking operation?

How to gracefully stop a thread that is running a blocking operation?

In general, you can't. But there are things you can do about some specific operations. For example, you can try interrupting the thread. In a case such as your example, where you don't have direct access to the Thread in which the task is running, you can use Future.cancel():

serverFuture.cancel(true);

But blocking operations do not necessarily get interrupted when their threads do. Those that do are generally documented to throw InterruptedException, and that is not among the exceptions ServerSocket.accept() is declared to throw. For that method in particular, your best bet probably involves using ServerSocket.setSoTimeout() to put a suitable upper bound on the amount of time that accept() will block. Using a relatively short timeout and performing the accept() in a loop would allow you to check periodically whether to abort the task.

Overall, then, you need to choose a strategy appropriate to the work you are trying to cancel, and you may need to expend some design effort to make that task cleanly interruptible.

How to interrupt or kill a java thread while it's running

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.

Shutdown a java app (multiple threads) gracefully

The problem is that as soon as the shutdown hook thread completes, the process is halted, you need to have the shutdown hook thread wait for the main thread.

Copied from https://stackoverflow.com/a/2922031/1544715

From the docs:

When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt.

Gracefully shutdown a program with multiple threads having infinite while loop

I need help to efficiently implement a Shutdown hook which can effectively STOP all the threads.

If you have any fields that are shared between multiple threads, they need to be synchronized. In this case your stop should be volatile. Without this, there is nothing that ensures that the threads will see the value of stop change to true. See this tutorial for information about atomic access.

See: Using boolean var for stopping threads

Couple other comments:

  • If you are starting a number of threads, you should consider using an ExecutorService

  • Your while loop is inside of a synchronized block. This does nothing and the stop field will not get memory synchronized since it gets updated externally while inside of the block.

  • Another way to stop a thread would be to interrupt() it. See this tutorial.

      while (!thread.currentThread().isInterrupted()) {
    ...
    }
    ...
    t.interrupt();


Related Topics



Leave a reply



Submit