Alin
Alin

Reputation: 314

JVM and main thread are still running after System.exit()

I need to shut down the application completely after ThreadPoolExecutor completes the currently executing tasks.For this I added the below code:

private void stopAppGracefully()
{
    MyApplication.executor.shutdown();

    System.exit(0);

    Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {

        logger.debug("Called the addShutdownHook()");

        //Wait infinitely till executor shut down
        while(!MyApplication.executor.isTerminated())
        {
          continue;
        }

        int queued = MyApplication.executor.getQueue().size();
        int active = MyApplication.executor.getActiveCount();
        int notCompleted = queued + active; // approximate

        long submitted = MyApplication.executor.getTaskCount();
        long completed = MyApplication.executor.getCompletedTaskCount();
        long notCompleted2 = submitted - completed; // approximate

        logger.debug("App is down..queued...:"+queued);
        logger.debug("App is down..active...:"+active);
        logger.debug("App is down..queued + active...:"+notCompleted);

        logger.debug("App is down..submitted...:"+submitted);
        logger.debug("App  is down..completed...:"+completed);
        logger.debug("App is down..submitted - completed...:"+notCompleted2);

        System.gc();

        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);

        for (int i = 0; i < threadArray.length; i++)
        {
          logger.debug("Remaining threads: "+ threadArray[i].getName());
        }
      }
    });
}

But I see the below information in logs:

20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 292 - App is down..queued...:0
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 293 - App is down..active...:0
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 294 - App is down..queued + active...:0
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 296 - App is down..submitted...:43
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 297 - App is down..completed...:43
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 298 - App is down..submitted - completed...:0
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Finalizer
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Reference Handler
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Thread-3
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Thread-2
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Thread-1
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: main
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Signal Dispatcher

Still seven threads are active. How to kill/stop these threads ?

I need to stop/kill all the threads belonging to the application.

Upvotes: 0

Views: 1283

Answers (3)

Federico Luzzi
Federico Luzzi

Reputation: 128

From the Java documentation we see that the System.exit( int ) method basically does the same work as manually calling the Runtime.getRuntime().exit( int ) method. Then again, have a look at the Java documentation of the addShutdownHook( Thread ) method. Quoting that:

Once the shutdown sequence has begun it is impossible to register a new shutdown hook or de-register a previously-registered hook. Attempting either of these operations will cause an IllegalStateException to be thrown.

Having read this, you probably have a synchronization error, in which the VM starts preparing the halting phase when the System.exit( int ) method is executed, but then, before the actual shutdown sequence starts, the addShutdownHook( Thread ) line is executed. The result is that it tells you there are threads running because effectively, they are, since the VM hasn't completely shut down yet.

Upvotes: 0

Jesper
Jesper

Reputation: 206816

ExecutorService.shutdown() does not immediately kill all running tasks and stop all threads. It will continue to run the tasks that are currently running. Note that shutdown() doesn't wait - it immediately returns, and current tasks may at that point still be running.

You can call awaitTermination(...) to wait for the currently running tasks to finish, or shutdownNow() which does indeed attempt to kill all currently running tasks.

To attempt to shutdown an ExecutorService gracefully, and then forcefully if it doesn't stop within a certain amount of time, you can use the following:

// Initiate graceful shutdown
executorService.shutdown();

try {
    // Wait one minute for tasks to finish
    boolean terminated = executorService.awaitTermination(1L, TimeUnit.MINUTES);

    if (!terminated) {
        // If not terminated after one minute, shutdown forcefully
        executorService.shutdownNow();
    }
} catch (InterruptedException e) {
    System.err.println("Interrupted while awaiting termination");
}

Upvotes: 2

xenteros
xenteros

Reputation: 15842

On Linux, you can use kill -9 with PID. On Windows, go to task manager and end task.

enter image description here

Upvotes: 0

Related Questions