namalfernandolk
namalfernandolk

Reputation: 9134

How to stop / kill multiple threads after a Time-Out value in java

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);

}

Upvotes: 0

Views: 3229

Answers (4)

Loganathan Mohanraj
Loganathan Mohanraj

Reputation: 1874

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

Upvotes: 2

zubergu
zubergu

Reputation: 3706

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

Upvotes: 1

Jose Martinez
Jose Martinez

Reputation: 11992

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.

Upvotes: 1

Nathan Hughes
Nathan Hughes

Reputation: 96385

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.

Upvotes: 4

Related Questions