0

I want to stop / kill all Threads (Runnables) started by Main after a given timeout. I tried to do as mentioned below. But it is not working as expected. Apart from that, I tried with the Thread.interrupt() but the results is negative. I tried thread.stop(). It is working but deprecated.

Can anyone give some idea on this?

Note : I'm focusing on a solution for Runnables not Callables. And I'm trying to do this bymodifying only the client code (Main). Not the Threads (Supplier)

Main

Thread      roxtoursThrd            = new Thread(new Supplier("roxtours", 1));
Thread      bluevacationsThrd       = new Thread(new Supplier("bluevacations", 1)); 
Thread      elixerThrd              = new Thread(new Supplier("elixer", 1)); 

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);

taskExecutor.execute(roxtoursThrd);
taskExecutor.execute(bluevacationsThrd);
taskExecutor.execute(elixerThrd);

taskExecutor.shutdown();
// taskExecutor.shutdownNow(); // This is also not stopping threads. They continue.

try {
  taskExecutor.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
  e.printStackTrace();
}

Supplier.java

public class Supplier implements Runnable {

    public Supplier(String name, int count) {
        this.name   = name;
        this.count  = count;
    }

    @Override
    public void run() {

        try {

           // Some time consuming operations (URL Connections, XML Decoding, DB Queries etc etc) are goes in here.

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    String  name    = null;
    int     count   = 0;

    Logger  logger  = Logger.getLogger(Supplier.class);

}
ironwood
  • 8,936
  • 15
  • 65
  • 114
  • What does that mean "not working as expected"? What would you expect this piece of code to do then what was different from result it gives? – zubergu Jul 28 '15 at 12:21
  • @zubergu : Expected : I want to stop the supplier threads after the given tim-out. But it is not stopping and continues. So, that is the unexpected! – ironwood Jul 28 '15 at 12:24
  • If you interrupt a thread with `interrupt()`, the thread has to check if it was interrupted periodically in its `run()` method by calling `isInterrupted()` – halloei Jul 28 '15 at 12:27

4 Answers4

4

Making the executor's tasks respond to interruption will require changing the code for the Suppliers. Interruption is cooperative; the thread being interrupted gets a flag set on it, but it's up to the thread to decide how to handle it. If your Runnable doesn't act on it, as in your example, then nothing happens, the thread just keeps on executing.

The Executor can only cancel threads that respond to interruption, see the API documentation for ExecutorService.shutdownNow:

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.

A thread can check its flag with the Thread#isInterrupted method. Your Runnable task should check Thread.getCurrentThread().isInterrupted().

If a thread is waiting or sleeping when the interrupted flag is set then an InterruptedException will be thrown and the flag will be cleared.

Do not use Thread#setDaemon(true) unless you're prepared for those threads to disappear suddenly with no warning and no chance to clean up pending tasks when the rest of the application shuts down.

The other option is the deprecated Thread#stop method, which causes ThreadDeath to be thrown. Unlike interruption, this is not cooperative, and it's between difficult and impossible to write code that can predictably and cleanly terminate when this exception occurs, because ThreadDeath can be thrown anywhere, unlike InterruptedException, which is much more manageable since it is only thrown from specific blocking calls.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
2

Use shutdownNow() instead of shutdown(). The shutdown() will initiate the shutdown and it will not accept any new tasks but you never know when the threads will be actually stopped. The shutdownNow() will immediately attempts to stop all the active threads and this will return all the active threads which are awaiting for execution.

Again there is no guarantee that all the threads will be stopped immediately (Threads will go for a graceful shutdown and it may take time based on the task given to the thread). We have to use either of the below methods to wait till all the threads are completed its execution.

executor.awaitTermination(...);

or

while (! executor.isTerminated()) {
        // Sleep for few milliseconds...
}

Refer the doc: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdown%28%29

Loganathan Mohanraj
  • 1,736
  • 1
  • 13
  • 22
  • I tried this. But threads are not stopping. But when I check, isShutdown() immediately after that it returned true. But they continue. And shutDownNow() returns an empty list. – ironwood Jul 28 '15 at 13:43
  • In an answer for the question linked "http://stackoverflow.com/questions/10504172/how-to-shutdown-an-executorservice" I found that "When calling shutdownNow, the executor will (generally) try to interrupt the threads that it manages. To make the shutdown graceful, you need to catch the interrupted exception in the threads or check the interrupted status. If you don't your threads will run forever and your executor will never be able to shutdown.". – ironwood Jul 28 '15 at 23:43
1

If you want to interrupt threads, you have to provide interruption entrance point. Sleep for a very short time, for example, then catch and handle InterruptionException.

Next what you can do is make use of isInterrupted() method in every iteration and the handle that as well.

Other approach would be to make all the threads daemons with setDaemon(), as they would be killed after main thread finishes, but this would be useful only if main was to be stopped.

In response to your edit/updated question: excerpt from shutdownNow() documentation

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.

So either you prepare you application to work as multi-threaded or you stick to single thread.

Also, see How do you kill a thread in Java?.

And the most important link from the question above: http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

Community
  • 1
  • 1
zubergu
  • 3,646
  • 3
  • 25
  • 38
  • Actually there's no main iteration in my actual code. I created this dummy one just to create a process taking some time. My run is single flow one and it some areas get times (URL Connections, DB Queries etc etc). So, I'm basically focussing on the killing/ stopping threads at the client side. Not by modifying within the supplier thread itself – ironwood Jul 28 '15 at 13:58
  • @Namalak I answered your question as it was. I don't know what stopping thread on the client side would mean in this context. Provide some code that relates to your real problem instead of wasting our time on something that wouldnt help you. – zubergu Jul 28 '15 at 14:07
  • Appology if it wasted your time. But I learned a lot from it. Didn't you read the "Note"? I have clearly mentioned "I'm trying to do this bymodifying only the client code (Main). Not the Threads (Supplier)". Any way I removed the test loop and added a comment in there to mention all the time consuming operations. – ironwood Jul 28 '15 at 14:12
  • @Namalak look at the time line of your actions. I left my crystal ball home, so can't lookup future. – zubergu Jul 28 '15 at 14:15
  • Why you want to loo through your crystal ball on the supplier thread when the requirement is to stop it at the client side without touching the supplier thread? And if you want to put that code within the run I will have to put number of classes contains thousands of lines. – ironwood Jul 28 '15 at 14:22
  • @Namalak Never mind the crystal ball, see the updated answer. – zubergu Jul 28 '15 at 14:42
  • Thank you very much zubergu. Information in your answer is very important and helpful. Thank you for the answer and your understanding! +1. – ironwood Jul 28 '15 at 18:15
1

Your thread's run method is not blocking, hence it does not run into a situation where an InterruptedException is thrown.

When a Thread is inerrupted, besides throwing an exception if it is blocking, it also has its interrupted status set, that is to say the method Thread#isInterrupted() returns true. Also, the method Thread#interrupted also returns true, but with the latter the interrupted status of the thread is cleared.

In your example you are not blocking nor are you checking the threads inerrupted status.

EDIT: Since you are not checking to see if the thread is interupted nor are you blocking, then you can't stop the threads explicitly, but you can stop them by making them daemon threads and then when your main thread (which is a user thread) finishes, all the other daemon threads will stop. Main difference between daemon thread and user thread is that as soon as all user thread finish execution java program or JVM terminates itself, JVM doesn't wait for daemon thread to finish there execution.

Jose Martinez
  • 11,452
  • 7
  • 53
  • 68
  • Thank you for the information. But here I am mainly focusing on the killing/ stopping threads at the client side. Not by modifying within the supplier thread itself. – ironwood Jul 28 '15 at 13:54
  • I added an edit to address that. Maybe that helps resolve this. – Jose Martinez Jul 28 '15 at 14:22