How does Java achieve an elegant stop?Get to the bottom of

Posted by brandtj on Wed, 20 May 2020 04:01:28 +0200

Traveling in the Java world, if you can have a pair of eyes that are good at discovery, there are many things to watch carefully, plus patience and help, you will often taste different things carefully.

With this sharing, you can easily get the following points, which are absolutely rewarding.

a) How do you make Java programs look elegant?Thoughts make sense!

b) Use scenarios for addShutdownHook?Use is king!

c) What exactly is the addShutdownHook hook function?Get to the bottom of!

1. How do you make Java programs look elegant?

Whether it's a self-study framework for basic services, or an analysis of open source project sources, careful Java development classmates will find thatRuntime.getRuntime(). addShutdownHook, what exactly is this sentence for?

Next let's go and see if it smells good?

Ali Open Source Data Synchronization Artifact Canal started with part of the source code:

Part of the source code under Apache for Flume startup for mass log collection:


Looking up at an open source project, you might want to extract some commonalities from it (the same code will taste if it encounters it many times), write a snippet and run (stand on the shoulder of the flume source, take off).

 1 import java.util.concurrent.ScheduledThreadPoolExecutor;
 2 import java.util.concurrent.TimeUnit;
 4 /**
 5  * Experience Java Grace Stop
 6  *
 7  * @author An Ape Novel
 8  */
 9 public class Application {
11     /**
12      * Monitoring Services
13      */
14     private ScheduledThreadPoolExecutor monitorService;
16     public Application() {
17         monitorService = new ScheduledThreadPoolExecutor(1);
18     }
20     /**
21      * Start the monitoring service to monitor memory information
22      */
23     public void start() {
24         System.out.println(String.format("Start Monitoring Service %s", Thread.currentThread().getId()));
25         monitorService.scheduleWithFixedDelay(new Runnable() {
26             @Override
27             public void run() {
28                 System.out.println(String.format("Maximum memory: %dm  Allocated memory: %dm  Remaining space in allocated memory: %dm  Maximum available memory: %dm",
29                         Runtime.getRuntime().maxMemory() / 1024 / 1024,
30                         Runtime.getRuntime().totalMemory() / 1024 / 1024,
31                         Runtime.getRuntime().freeMemory() / 1024 / 1024,
32                         (Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory() +
33                                 Runtime.getRuntime().freeMemory()) / 1024 / 1024));
34             }
35         }, 2, 2, TimeUnit.SECONDS);
36     }
38     /**
39      * Release resources (code from flume source)
40      * Mainly used to close thread pools (unseen students don't get tangled, treated as black boxes)
41      */
42     public void stop() {
43         System.out.println(String.format("Start closing thread pool %s", Thread.currentThread().getId()));
44         if (monitorService != null) {
45             monitorService.shutdown();
46             try {
47                 monitorService.awaitTermination(10, TimeUnit.SECONDS);
48             } catch (InterruptedException e) {
49                 System.err.println("Interrupted while waiting for monitor service to stop");
50             }
51             if (!monitorService.isTerminated()) {
52                 monitorService.shutdownNow();
53                 try {
54                     while (!monitorService.isTerminated()) {
55                         monitorService.awaitTermination(10, TimeUnit.SECONDS);
56                     }
57                 } catch (InterruptedException e) {
58                     System.err.println("Interrupted while waiting for monitor service to stop");
59                 }
60             }
61         }
62         System.out.println(String.format("Thread pool shutdown complete %s", Thread.currentThread().getId()));
63     }
65     /**
66      * Application Entry
67      */
68     public static void main(String[] args) {
69         Application application = new Application();
70         // Start the service (monitor the output of memory information every once in a while)
71         application.start();
73         // Add hooks for elegant stopping (mainly to verify the role of hooks)
74         final Application appReference = application;
75         Runtime.getRuntime().addShutdownHook(new Thread("shutdown-hook") {
76             @Override
77             public void run() {
78                 System.out.println("Receive a signal to quit, start cleaning up the battlefield, release resources, and complete an elegant stop");
79                 appReference.stop();
80             }
81         });
82         System.out.println("Service startup complete");
83     }
84 }

I know very well that there should be very few students who have the patience to read the source code in the articles, so I will give you a simple stroke with the picture.

Label 1: The start method uses the thread pool to start a thread to monitor memory information on a regular basis.

The Label 2:stop method is used to close the thread pool and release resources before exiting the program.

The program runs as follows.


When kill ing occurs, the program does release resources, and the effect is really elegant.


Is it true that everything seems so natural and everything is so perfect?What happens if kill-9 is used during the killing process?


Whoop!The result will not be deceptive, when kill-9 is used, it will appear very rough, no matter what resources are released, whether 3721 or terminate the program.

It is estimated that many students are good at killing process with kill-9. For online application security, let's kill process with kill-15 command, which will give the application some time to clean up the battlefield and release resources.

Okay, by savoring it carefully and using JDK's own addShutdownHook to help with the app, you can really make online services run elegantly.

Thoughts make sense!

2. Use scenarios for addShutdownHook?

Code experimentation has shown that addShutdownHook(new Thread(){}) is a thread to be executed before the JVM is destroyed, so any scenario involving resource recycling should be satisfied. Here are a few simple examples.

a) The data synchronization artifact Canal uses it to close socket links, release working nodes of canal, clean up cache information, etc.

b) Mass log collection Flume uses it to close thread pool resources, stop worker threads, etc.

c) Perform specific business logic, shut down resources, etc. when the application exits normally.

d) In case of OOM downtime, CTRL+C, or kill pid, resulting in abnormal JVM exit, it is possible to add necessary rescue measures.

In fact, traveling in the Java world is unexpected and impossible!

3. What is the addShutdownHook hook function?

Shaving roots, ask after all!


Hook is translated as hook, which means hanging things.


As shown in the figure, in real life, to make bacon, first hook the meat with a hook and then hang it on a bamboo pole. This should be the role of a hook.

Life is like this, and all design concepts come from life, and in the Java world, too.


As shown in the source code of Runtime above, following the core idea of Java,'Everything is an object', you can think of the addShutdownHook method as a hook, which is actually better called a hook function, while the meat in real life can be abstracted as a thread that releases resources.

As long as this hook function is available, it provides the ability to expand, and developers can hang various custom scene implementations on the hook. This design is absolutely fragrant!That's why different applications, such as Canal, Flume, Tomcat, have different implementations when serving gracefully.

In plain words, with the hook function, if you want to hang something, you can set it yourself according to your mood.

Further digging will reveal that since the underlying data structure is stored in Map, support for developers to hang multiple shutdownHook s brings unlimited possibilities (and an infinite amount of "excitement" to experience).


Okay, avoid the big head, just shave here, and if you're interested, you can continue shaving along your way.

4. Send your message at the end

As a developer: To have eyes that are discoverable, to discover the beauty of code.

As a developer: Always think about whether simple refactoring can make your program run smoother in the face of current projects.

As a research and development personnel: to see, understand, refine and practice more.

As a developer: Don't give up the code, because the program will make life.

This sharing is here, I hope it will help you.Talk about technology, business, spray architecture together, avoid detours and don't step on big pits.

We will continue to output the original and share it with you. Please look forward to it!Focus on the Public Number of the Same Name: In an ape novel, reply to "1024" to get advanced information about the job you're prepared for.

Topics: Java jvm Apache JDK