Graceful shutdown of threads and executor

前端 未结 5 1495
一个人的身影
一个人的身影 2020-11-29 18:42

The following piece of code tries to accompolish this.

The code loops forever and checks if there are any pending requests to be processed. If there is any, it creat

相关标签:
5条回答
  • 2020-11-29 19:10

    The book "Java Concurrency in Practice" states:

    7.4. JVM Shutdown

    The JVM can shut down in either an orderly or abrupt manner. An orderly shutdown is initiated when the last "normal" (nondaemon) thread terminates, someone calls System.exit, or by other platform-specific means (such as sending a SIGINT or hitting Ctrl-C). [...]

    7.4.1. Shutdown Hooks

    In an orderly shutdown, the JVM first starts all registered shutdown hooks. Shutdown hooks are unstarted threads that are registered with Runtime.addShutdownHook. The JVM makes no guarantees on the order in which shutdown hooks are started. If any application threads (daemon or nondaemon) are still running at shutdown time, they continue to run concurrently with the shutdown process. When all shutdown hooks have completed, the JVM may choose to run finalizers if runFinalizersOnExit is true, and then halts. The JVM makes no attempt to stop or interrupt any application threads that are still running at shutdown time; they are abruptly terminated when the JVM eventually halts. If the shutdown hooks or finalizers don't complete, then the orderly shutdown process "hangs" and the JVM must be shut down abruptly. [...]

    The important bits are, "The JVM makes no attempt to stop or interrupt any application threads that are still running at shutdown time; they are abruptly terminated when the JVM eventually halts." so I suppose the connection to the DB will abruptly terminate, if no shutdown hooks are there to do a graceful clean up (if you are using frameworks, they usually do provide such shutdown hooks). In my experience, session to the DB can remain until it is timed out by the DB, etc. when the app. is terminated without such hooks.

    0 讨论(0)
  • 2020-11-29 19:21

    Since adding a shutdown hook to explicitly call shutdown() didn't work for me, I found an easy solution in Google's Guava: com.google.common.util.concurrent.MoreExecutors.getExitingExecutorService.

    0 讨论(0)
  • 2020-11-29 19:21

    You can either call shutdown() on the ExecutorService:

    Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.

    or you can call 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.

    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.

    Which one you call depends how badly you want it to stop....

    0 讨论(0)
  • 2020-11-29 19:25

    A typical orderly shutdown of an ExecutorService might look something like this:

    final ExecutorService executor;
    
    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            executor.shutdown();
            if (!executor.awaitTermination(SHUTDOWN_TIME)) { //optional *
                Logger.log("Executor did not terminate in the specified time."); //optional *
                List<Runnable> droppedTasks = executor.shutdownNow(); //optional **
                Logger.log("Executor was abruptly shut down. " + droppedTasks.size() + " tasks will not be executed."); //optional **
            }
        }
    });
    

    *You can log that the executor still had tasks to process after waiting the time you were willing to wait.
    **You can attempt to force the executor's worker Threads to abandon their current tasks and ensure they don't start any of the remaining ones.

    Note that the solution above will work when a user issues an interrupt to your java process or when your ExecutorService only contains daemon threads. If, instead, the ExecutorService contains non-daemon threads that haven't completed, the JVM won't try to shutdown, and therefore the shutdown hooks won't be invoked.

    If attempting to shutdown a process as part of a discrete application lifecycle (not a service) then shutdown code should not be placed inside a shutdown hook but at the appropriate location where the program is designed to terminate.

    0 讨论(0)
  • 2020-11-29 19:25

    I had similar issue, i use to get error like

    o.a.c.loader.WebappClassLoaderBase :: The web application [ROOT] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: sun.misc.Unsafe.park(Native Method) java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)

    Bellow code fixed it

    private ThreadPoolExecutor executorPool;
    
    @PostConstruct
    public void init() {
        log.debug("Initializing ThreadPoolExecutor");
        executorPool = new ThreadPoolExecutor(1, 3, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1));
    }
    
    @PreDestroy
    public void destroy() {
        log.debug("Shuting down ThreadPoolExecutor");
        executorPool.shutdown();
    }
    
    0 讨论(0)
提交回复
热议问题