Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop a java thread gracefully?

I wrote a thread, it is taking too much time to execute and it seems it is not completely done. I want to stop the thread gracefully. Any help ?

like image 507
Puru Avatar asked Jul 07 '10 12:07

Puru


People also ask

How do you gracefully exit a thread?

To stop the thread, set stop to true . I think you must do it manually this way. After all, only the code running in the thread has any idea what is and isn't graceful. Note that you either need to use locking or make the field volatile to make sure the reading thread sees changes from the writing thread.

What will be the best way to stop a Java thread?

Modern ways to suspend/stop a thread are by using a boolean flag and Thread. interrupt() method. Using a boolean flag: We can define a boolean variable which is used for stopping/killing threads say 'exit'. Whenever we want to stop a thread, the 'exit' variable will be set to true.

How do you force a thread to stop in Java?

To end the thread before going through the current loop you can use the break keyword. This avoids using deprecated methods such as Thread. stop() . The thread will finish the current task and then stop itself naturally.

How do you stop a thread from signaling?

To stop a worker thread call workerThread. interrupt() this will cause certain methods (like Thread. sleep()) to throw an interrupted exception. If your threads don't call interruptable methods then you need to check the interrupted status.


2 Answers

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..

like image 137
Jack Avatar answered Oct 11 '22 13:10

Jack


The bad part about using a flag to stop your thread is that if the thread is waiting or sleeping then you have to wait for it to finish waiting/sleeping. If you call the interrupt method on the thread then that will cause the wait or sleep call to be exited with an InterruptedException.

(A second bad part about the flag approach is that most nontrivial code is going to be utilizing libraries like java.util.concurrent, where the classes are specifically designed to use interruption to cancel. Trying to use the hand rolled flag in a task passed into an Executor is going to be awkward.)

Calling interrupt() also sets an interrupted property that you can use as a flag to check whether to quit (in the event that the thread is not waiting or sleeping).

You can write the thread's run method so that the InterruptedException is caught outside whatever looping logic the thread is doing, or you can catch the exception within the loop and close to the call throwing the exception, setting the interrupt flag inside the catch block for the InterruptedException so that the thread doesn't lose track of the fact that it was interrupted. The interrupted thread can still keep control and finish processing on its own terms.

Say I want to write a worker thread that does work in increments, where there's a sleep in the middle for some reason, and I don't want quitting the sleep to make processing quit without doing the remaining work for that increment, I only want it to quit if it is in-between increments:

class MyThread extends Thread {     public void run()     {         while (!Thread.currentThread().isInterrupted())         {             doFirstPartOfIncrement();             try {                 Thread.sleep(10000L);             } catch (InterruptedException e) {                 // restore interrupt flag                 Thread.currentThread().interrupt();             }             doSecondPartOfIncrement();         }     } } 

Here is an answer to a similar question, including example code.

like image 32
Nathan Hughes Avatar answered Oct 11 '22 13:10

Nathan Hughes