新聞中心
Java應(yīng)用程序退出的觸發(fā)機制有:

創(chuàng)新互聯(lián)公司服務(wù)項目包括古浪網(wǎng)站建設(shè)、古浪網(wǎng)站制作、古浪網(wǎng)頁制作以及古浪網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,古浪網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到古浪省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
- 自動結(jié)束:應(yīng)用沒有存活線程或只有后臺線程時;
- System.exit(0);
- kill 或 ctrl+C;
- kill -9 強制退出;
如何做到應(yīng)用程序平滑停止
程序的退出就像關(guān)機一樣,我們希望關(guān)機時平滑關(guān)機,保證所有應(yīng)用程序的數(shù)據(jù)都保存了。就像現(xiàn)在在寫得blog,希望關(guān)機的時候能被保存好到草稿箱里。
我們的的Java程序中經(jīng)常有一種常駐的任務(wù)或服務(wù),如消息消費端、服務(wù)提供者,我們期望停止也是平滑的不會出現(xiàn)事務(wù)執(zhí)行到一半產(chǎn)生臟數(shù)據(jù)。
java對這塊的支持是通過鉤子線程實現(xiàn)。每個Java進程都可以注冊鉤子線程,鉤子線程程在程序退出的前被執(zhí)行(kill -9強制退出除外)。注冊鉤子線程代碼如下:
- Runtime.getRuntime().addShutdownHook(t);
我們可以在鉤子線程里做一些善后數(shù)據(jù)清理等事情,以保證程序是平滑退出的。
一般服務(wù)或框架運行都要考慮其生命周期:
如spring容器的context.stop()方法。
再如線程池ExecutorService的shutdown方法,它會保證不接受新任務(wù),并把未執(zhí)行完的任務(wù)做完。
我們再設(shè)計服務(wù)的時候也要考慮到停止時的stop方法,以便于退出時由鉤子線程調(diào)用。
注冊了鉤子線程后,程序收到退出信號后,會保持程序運行,直到鉤子線程執(zhí)行完畢,才把程序的所有線程停止并退出,下面示例代碼可以說明這一點:
- public class ShutDownTest {
- public static void main(String[] args) {
- //注冊***個鉤子
- Runtime.getRuntime().addShutdownHook(new Thread() {
- public void run() {
- try {
- Thread.currentThread().sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("clean task1 completed.");
- }
- });
- //注冊第二個鉤子
- Runtime.getRuntime().addShutdownHook(new Thread() {
- public void run() {
- try {
- Thread.currentThread().sleep(10000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("clean task2 completed");
- }
- });
- //啟動子線程
- new Thread() {
- public void run() {
- while (true) {
- try {
- Thread.currentThread().sleep(1000);
- System.out.println("sub thread is running");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }.start();
- //程序退出
- System.exit(0);
- }
- }
程序輸出:
- sub thread is running
- sub thread is running
- sub thread is running
- sub thread is running
- clean task1 completed.
- sub thread is running
- sub thread is running
- sub thread is running
- sub thread is running
- sub thread is running
- clean task2 completed
注意點:鉤子線程里只處理善后,目標(biāo)是盡可能快的退出且不保證有臟數(shù)據(jù)。如果鉤子線程里做過多事情,或者發(fā)生阻塞,那么可能出現(xiàn)kill失效,程序不能退出的情況,這是需要強制退出。
如以下程序會導(dǎo)致kill失效,需要強制退出,因為鉤子線程阻塞了:
- public class ShutDownTest {
- public static void main(String[] args) {
- //注冊鉤子
- Runtime.getRuntime().addShutdownHook(new Thread() {
- public void run() {
- synchronized (ShutdownFileTest.class) {
- try {
- ShutdownFileTest.class.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- });
- //啟動子線程
- new Thread() {
- public void run() {
- while (true) {
- try {
- Thread.currentThread().sleep(1000);
- System.out.println("sub thread is running");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }.start();
- System.exit(0);
- }
- }
程序退出機制選擇
觸發(fā)程序退出的在前面已經(jīng)提到過,但是為了停止方便、安全和優(yōu)雅,一般我們推薦幾種操控性更強的退出機制。常見的推薦機制有以下幾種:
1.kill
在linux里用的比較多,向進程發(fā)送退出信號,java進程收到后平滑退出。
2.shutdownfile
系統(tǒng)創(chuàng)建一個shutdown file.并監(jiān)聽shutdown file是否存在。如果發(fā)現(xiàn)shutdown file不存在了,那么調(diào)用System.exit,將程序退出。
如果期望只有特定的人才能終止該程序,那么你可以給文件設(shè)定權(quán)限,這樣就只有特定的人可以終止程序。
以下代碼是個簡單的例子:
- import java.io.File;
- import java.io.IOException;
- public class ShutdownFileTest {
- public static void main(String[] args) {
- // 啟動子線程
- new Thread() {
- public void run() {
- while (true) {
- try {
- Thread.currentThread().sleep(1000);
- System.out.println("sub thread is running");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }.start();
- //啟動shutdownfile監(jiān)聽線程
- new Thread() {
- public void run() {
- File shutDownFile = new File("a.shutdown");
- // create shut down file
- if (!shutDownFile.exists()) {
- try {
- shutDownFile.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- // watch for file deleted then shutdown
- while (true) {
- try {
- if (shutDownFile.exists()) {
- Thread.currentThread().sleep(1000);
- } else {
- System.exit(0);
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }.start();
- }
- }
3.打開一個端口,監(jiān)聽端口里的命令,收到命令后調(diào)用System.exit。
這個似乎不常見,也比較麻煩。
4.JMX
通過JMX的mbean遠(yuǎn)程控制來實現(xiàn)。
在這個鏈接里有看到例子:how-to-stop-java-process-gracefully
分享文章:設(shè)計Java應(yīng)用程序的平滑停止
文章路徑:http://www.fisionsoft.com.cn/article/cdojdjh.html


咨詢
建站咨詢
