Jan Vladimir Mostert Jan Vladimir Mostert - 1 month ago 6
Java Question

Block Java application from exiting until ThreadPool is empty

I've got an

ExecutorService
sitting inside a singleton class which receives tasks from many different classes. On application shutdown, I need to wait for the pool to be empty before I allow the application to exit.

private static NotificationService instance = null;

private ExecutorService executorService = Executors.newFixedThreadPool(25);

public static synchronized NotificationService getInstance() {
if (instance == null) {
instance = new NotificationService(true);
}
return instance;
}


While using this
NotificationService
, it frequently happens that I restart the application and the
executorService
hasn't finished processing all the notifications.

For Testing, I can manually shutdown the executorService and wait until all tasks are completed.

public static boolean canExit() throws InterruptedException {
NotificationService service = getInstance();
service.executorService.shutdown();
service.executorService.awaitTermination(30, TimeUnit.SECONDS);
return service.executorService.isTerminated();
}


Is it reliable and safe to override the
finalize
method and wait there until the pool is empty? From what I've read, finalize is not always called, especially not when using a singleton class.

@Override
protected void finalize() throws Throwable {
while (!canExit()){
Thread.sleep(100);
}
super.finalize();
}


This code is included in a library that will be included in another application, so there's no main method where I can wait until the pool is empty, unless I force the person using it to do so which is not great.

What is the correct way to stall the application (for a reasonable amount of time) from terminating until the pool is empty?

Answer

You can use addShutdownHook to catch the process termination event and wait for the pool there.

example:

 Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
        NotificationService service = getInstance();
        service.executorService.shutdown();
        service.executorService.awaitTermination(30, TimeUnit.SECONDS);
      }
    });
Comments