2

I am running simple thread which has run method as follows

public run()
while(!stopFlag){
   // print something Line 1
   // print something Line 2
   // print something Line 3
   // print something Line 4
}

If I run this thread through ExecutorService viz

ExecutorService exs = Executors.newFixedThreadPool(5);
exs.execute(new MyThread));

I stop the ExecutorService

exs.shutdown();

But this does not stop the thread as flag is not set to false. In another question related to same topic I was asked to properly handle InterruptedException which is caused when exs.shutdown() is called. But in this case I am not doing any action that can throw InterruptedException.

What is the standard way to handle such case ?

Further question Answer given by Sabir says "If your runnable doesn't respond well to interrupts, nothing can be done to stop it other than shutting down the JVM. ".This seems to be my case.

But how to introduce handling of InterruptedException; if I am not calling any method that throws interrupted exception?

Community
  • 1
  • 1
Kaushik Lele
  • 6,439
  • 13
  • 50
  • 76
  • You're not showing enough of your thread code. Also, that bit you do show won't compile. – Michael Markidis May 16 '17 at 06:03
  • Check if the thread has been interrupted. ie `while(!Thread.interrupted())` – matt May 16 '17 at 06:09
  • doc says : `This method does not wait for previously submitted tasks to * complete execution. Use awaitTermination * to do that.` – Jay Smith May 16 '17 at 06:09
  • The main thing is, when you are using a blocking api it throws an interrupted exception. If you are not using a blocking api, you have to check to see if the thread is interrupted. Then if it is interrupted, quit your loop or even throw an interrupted exception if you like. – matt May 16 '17 at 09:05

2 Answers2

2

If you are willing to shut your thread even if that flag remains true, you should use - ExecutorService.shutdownNow() method instead of ExecutorService.shutdown()

Quoting from Java Docs,

shutdown()

Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.

This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.

shutdownNow()

Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.

This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.

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.

For standard way, I will quote from JDK example from ExecutorService interface,

Usage Examples

Here is a sketch of a network service in which threads in a thread pool service incoming requests. It uses the preconfigured Executors.newFixedThreadPool factory method:    class NetworkService implements Runnable {    private final ServerSocket serverSocket;    private final ExecutorService pool;

   public NetworkService(int port, int poolSize)
       throws IOException {
     serverSocket = new ServerSocket(port);
     pool = Executors.newFixedThreadPool(poolSize);    }

   public void run() { // run the service
     try {
       for (;;) {
         pool.execute(new Handler(serverSocket.accept()));
       }
     } catch (IOException ex) {
       pool.shutdown();
     }    }  }

 class Handler implements Runnable {    private final Socket socket;   Handler(Socket socket) { this.socket = socket; }    public void run() {
     // read and service request on socket    }  }} The following method shuts down an ExecutorService in two phases, first by calling shutdown to reject incoming tasks, and then calling shutdownNow, if necessary, to cancel any lingering tasks:    void shutdownAndAwaitTermination(ExecutorService pool) {    pool.shutdown(); // Disable new tasks from being submitted    try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }    } catch (InterruptedException ie) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();    }  }}

Notice that there are no guarantees even with shutdownNow() .

EDIT : If I change your while(!stopFlag) to while(!Thread.currentThread().isInterrupted()) then thread with conditional loop get shutdown with shutdownNow() but not with shutdown() so thread gets interrupted with shutdownNow(). I am on JDK8 and Windows 8.1. I do have to put a sleep in main thread so that service can get time to set up the service and launch runnable. Thread gets launched, goes in while then stops when shutdownNow() is called. I don't get that behavior with shutdown() i.e. thread never comes out of while loop. So the approach to make your runnables responsible for interrupts should be there ,either by checking flags or handling exceptions. If your runnable doesn't respond well to interrupts, nothing can be done to stop it other than shutting down the JVM.

One good approach is shown here

Sabir Khan
  • 9,826
  • 7
  • 45
  • 98
  • I have edited my answer with the results that I see. `shutdownNow()` interrupts thread with while loop. – Sabir Khan May 16 '17 at 07:56
  • "If your runnable doesn't respond well to interrupts, nothing can be done to stop it other than shutting down the JVM. ".... this seems to be my case. :( – Kaushik Lele May 17 '17 at 04:10
  • But how to introduce handling of InterruptedException; if I am not calling any method that throws interrupted exception – Kaushik Lele May 17 '17 at 04:17
  • 1
    I am not sure what kind of operations are doing in that while loop but you just can't if not calling any methods that throws `InterruptedException`. You might encapsulate your `run()` method into something like , `private void runLogic() throws InterruptedException{}` to achieve that by calling `runLogic()` from `run()`. Also see [this](http://stackoverflow.com/questions/20958258/is-throwing-interruptedexception-essential-when-stopping-threads-can-i-use-anot) – Sabir Khan May 17 '17 at 05:06
0

well from your question I am assuming that you are trying to shutdown the process gracefully. In order to do so you need to register a shutdownHook to achieve it. Here is a sample code to achieve it.

package com.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadManager {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Runtime.getRuntime().addShutdownHook(new Thread(){
            MyThread myThread = null;
            @Override
            public void run(){
                System.out.println("Shutting down....");
                this.myThread.stopProcess();
            }
            public Thread setMyThread(MyThread myThread){
                this.myThread=myThread;
                return this;
            }
        }.setMyThread(myThread));
        ExecutorService exs = Executors.newFixedThreadPool(5);
        myThread.setName("User");
        exs.execute(myThread);
        exs.shutdownNow();
    }
}

And in MyThread.java will be look like following:-

package com.example;

public class MyThread extends Thread{
    private boolean stopFlag;

    @Override
    public void run(){
        while(!stopFlag){
           System.out.println(this.getName());
        }
    }
    public void stopProcess(){
        this.stopFlag=true;
    }
}

Now if you make a jar file of this code and run the in a Linux server to see how it is working, then follow these additional steps

Step 1> nohup java -jar MyThread.jar &

Press ctrl+c to exist Now find the pid using following command

Step 2> ps -ef| grep MyThread.jar

Once you got the pid than execute the following command to stop gracefully

Step 3>kill -TERM <Your PID>

When you check the nohub.out file, the output will looks something like following

User
User
.
.
.
User
Shutting down....
User
.
.

Remember if you try to shutdown using kill -9 than you will never see the Shutting down.... message.

@Sabir already discuss the difference between shutdown and shutdownNow. However I will never recommend you to use interrupt call while the threads are running. It might cause memory leak in real time environment.

Upadte 1:-

public static void main(String[] args) {
    MyThread myThreads[] = new MyThread[5];
    ExecutorService exs = Executors.newFixedThreadPool(5);
    for(int i=0;i<5;++i){
        MyThread myThread = new MyThread();
        myThread.setName("User "+i);
        exs.execute(myThread);
        myThreads[i] = myThread;
    }
    Runtime.getRuntime().addShutdownHook(new Thread(){
        MyThread myThreads[] = null;
        @Override
        public void run(){
            System.out.println("Shutting down....");
            for(MyThread myThread:myThreads){
                myThread.stopProcess();
            }
        }
        public Thread setMyThread(MyThread[] myThreads){
            this.myThreads=myThreads;
            return this;
        }
    }.setMyThread(myThreads));
    exs.shutdownNow();
}
  • So I have to create as many shutdown hooks as many tasks I submit to ExecutorService. So thought it is can one possible technical way; does not look elegant. From the discussion looks like one should implement Thread in elegant way in first place to avoid such nasty scenarios. – Kaushik Lele May 17 '17 at 04:15
  • Making your threads cancellable is altogether a specific segment within Java multi threading & most programmers miss that part. Assume an UI showing all threads in your JVM and you wish to provide a `cancel` button for threads , will you use `addShutdownHook`? shutdown hook is a JVM level concept and you should never assume that only your program is running in that JVM. – Sabir Khan May 17 '17 at 05:51
  • No you don't have to use many shutdown hooks. Why don't you use Array of threads. – Satyaprakash Nayak May 17 '17 at 06:03
  • Please check the updated code. And yes you have to be careful about the implementation of threads. @Sabir you can use JMX in case of remote access but this example is just a sudo code for desktop application. – Satyaprakash Nayak May 17 '17 at 06:25