Sending shut down signal to another thread in Java

2.1k views Asked by At

I have an application that runs something repeatedly in a while loop in a separate thread until the user triggers a shut down signal. I can send the signal from main thread to the worker thread by setting a (volatile) boolean field in the worker thread, but is there any other way of shut down/interrupt a thread, e.g. by means of any utility from 'java.util.concurrent'?

I have tried calling shutdown() or shutdownNow() method of the ExecutorService, but they fail to stop the worker thread. Also calling shutdown() and using !Thread.currentThread().isInterrupted() in the while condition as recommended here is failing to break the loop. The only other way I could find was to use a CountDownLatch, but here I would have to use CountDownLatch.getCount() != 0 in the condition for while loop, but the javadoc documentation of this method says

This method is typically used for debugging and testing purposes.

which makes it a questionable approach IMO. Below is my sample code

class Worker implements Runnable {
    //private volatile boolean shutdown = false; --> alternative to countdownlatch 
    @Override
    public void run() {

        while (countDownLatch.getCount() != 0) {
            //do some work    
        }
    }
}

public class App {
    public static void main(String[] args) {

    System.out.println("Press enter to stop");

    CountDownLatch countDownLatch = new CountDownLatch(1);

    ExecutorService es = Executors.newFixedThreadPool(1);
    es.execute(new Worker(countDownLatch));

    Scanner scanner = new Scanner(System.in);
    scanner.nextLine();

    System.out.println("Shut down signal received");

    countDownLatch.countDown();  //an alternative would be to set a boolean variable in worker

    es.shutdownNow();

}
}

Are there any other clean way of doing this?

3

There are 3 answers

0
RalphChapin On BEST ANSWER

Is there any other clean way of doing this? No. Stick with the (volatile) boolean.

I'm sure Thread.stop() would work, but there's no opportunity to clean up properly. Using interrupted()/isInterrupted() will work, but it's a bit more complicated than the boolean. Plus, there are times when you don't want to quit a loop just because it was interrupted. I've got code in a few places where I recover from an InterruptedException (or something similar), then check my boolean (or whatever) and, depending on its value, continue or not.

The boolean plays well with others. I've mentioned the interrupt. You might someday have 20 different reasons to stop the loop in any of 10 (or more) places. That boolean will fit right in; you can easily write code so that your thread always stops when the boolean is true, or never stops when its false, or whatever else you need done.

0
Vasanth On

You can get [ExecutorService][http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html] from [Executors][http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html]

With a reference to the ExecutorsService in the main thread, you can shutdown you ThreadPool on receiving a signal.

2
Vitruvie On

You must check Thread.interrupted() in your loop in order to shut it down with anything short of System.exit(). Then you can use thread.interrupt(), which is what ExecutorService.shutdown() uses anyway. If it's not working, show us your code for how you check isInterrupted() so we can fix it. Thread.stop() exists, but is deprecated with good reason, and shouldn't be used.