自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

設(shè)計(jì)Java應(yīng)用程序的平滑停止

開發(fā) 后端
程序的退出就像關(guān)機(jī)一樣,我們希望關(guān)機(jī)時(shí)平滑關(guān)機(jī),保證所有應(yīng)用程序的數(shù)據(jù)都保存了。就像現(xiàn)在在寫得blog,希望關(guān)機(jī)的時(shí)候能被保存好到草稿箱里。

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

  1. 自動(dòng)結(jié)束:應(yīng)用沒有存活線程或只有后臺(tái)線程時(shí);
  2. System.exit(0);
  3. kill 或 ctrl+C;
  4. kill -9 強(qiáng)制退出;

如何做到應(yīng)用程序平滑停止

程序的退出就像關(guān)機(jī)一樣,我們希望關(guān)機(jī)時(shí)平滑關(guān)機(jī),保證所有應(yīng)用程序的數(shù)據(jù)都保存了。就像現(xiàn)在在寫得blog,希望關(guān)機(jī)的時(shí)候能被保存好到草稿箱里。

我們的的Java程序中經(jīng)常有一種常駐的任務(wù)或服務(wù),如消息消費(fèi)端、服務(wù)提供者,我們期望停止也是平滑的不會(huì)出現(xiàn)事務(wù)執(zhí)行到一半產(chǎn)生臟數(shù)據(jù)。

 

java對(duì)這塊的支持是通過鉤子線程實(shí)現(xiàn)。每個(gè)Java進(jìn)程都可以注冊(cè)鉤子線程,鉤子線程程在程序退出的前被執(zhí)行(kill -9強(qiáng)制退出除外)。注冊(cè)鉤子線程代碼如下:

  1. Runtime.getRuntime().addShutdownHook(t); 

我們可以在鉤子線程里做一些善后數(shù)據(jù)清理等事情,以保證程序是平滑退出的。

一般服務(wù)或框架運(yùn)行都要考慮其生命周期:

如spring容器的context.stop()方法。

再如線程池ExecutorService的shutdown方法,它會(huì)保證不接受新任務(wù),并把未執(zhí)行完的任務(wù)做完。

 

我們?cè)僭O(shè)計(jì)服務(wù)的時(shí)候也要考慮到停止時(shí)的stop方法,以便于退出時(shí)由鉤子線程調(diào)用。

注冊(cè)了鉤子線程后,程序收到退出信號(hào)后,會(huì)保持程序運(yùn)行,直到鉤子線程執(zhí)行完畢,才把程序的所有線程停止并退出,下面示例代碼可以說明這一點(diǎn):

  1. public class ShutDownTest {  
  2.  
  3.     public static void main(String[] args) {  
  4.         //注冊(cè)***個(gè)鉤子  
  5.         Runtime.getRuntime().addShutdownHook(new Thread() {  
  6.  
  7.             public void run() {  
  8.                 try {  
  9.                     Thread.currentThread().sleep(5000);  
  10.                 } catch (InterruptedException e) {  
  11.                     e.printStackTrace();  
  12.                 }  
  13.                 System.out.println("clean task1 completed.");  
  14.             }  
  15.         });  
  16.         //注冊(cè)第二個(gè)鉤子  
  17.         Runtime.getRuntime().addShutdownHook(new Thread() {  
  18.  
  19.             public void run() {  
  20.                 try {  
  21.                     Thread.currentThread().sleep(10000);  
  22.                 } catch (InterruptedException e) {  
  23.                     e.printStackTrace();  
  24.                 }  
  25.                 System.out.println("clean task2 completed");  
  26.             }  
  27.         });  
  28.         //啟動(dòng)子線程  
  29.         new Thread() {  
  30.  
  31.             public void run() {  
  32.                 while (true) {  
  33.                     try {  
  34.                         Thread.currentThread().sleep(1000);  
  35.                         System.out.println("sub thread is running");  
  36.                     } catch (InterruptedException e) {  
  37.                         e.printStackTrace();  
  38.                     }  
  39.                 }  
  40.             }  
  41.         }.start();  
  42.         //程序退出  
  43.         System.exit(0);  
  44.     }  
  45.  

程序輸出:

  1. sub thread is running  
  2. sub thread is running  
  3. sub thread is running  
  4. sub thread is running  
  5. clean task1 completed.  
  6. sub thread is running  
  7. sub thread is running  
  8. sub thread is running  
  9. sub thread is running  
  10. sub thread is running  
  11. clean task2 completed 

注意點(diǎn):鉤子線程里只處理善后,目標(biāo)是盡可能快的退出且不保證有臟數(shù)據(jù)。如果鉤子線程里做過多事情,或者發(fā)生阻塞,那么可能出現(xiàn)kill失效,程序不能退出的情況,這是需要強(qiáng)制退出。

如以下程序會(huì)導(dǎo)致kill失效,需要強(qiáng)制退出,因?yàn)殂^子線程阻塞了:

  1. public class ShutDownTest {  
  2.  
  3.     public static void main(String[] args) {  
  4.         //注冊(cè)鉤子  
  5.         Runtime.getRuntime().addShutdownHook(new Thread() {  
  6.             public void run() {  
  7.                 synchronized (ShutdownFileTest.class) {  
  8.                     try {  
  9.                         ShutdownFileTest.class.wait();  
  10.                     } catch (InterruptedException e) {  
  11.                         e.printStackTrace();  
  12.                     }  
  13.                 }  
  14.             }  
  15.         });  
  16.         //啟動(dòng)子線程  
  17.         new Thread() {  
  18.             public void run() {  
  19.                 while (true) {  
  20.                     try {  
  21.                         Thread.currentThread().sleep(1000);  
  22.                         System.out.println("sub thread is running");  
  23.                     } catch (InterruptedException e) {  
  24.                         e.printStackTrace();  
  25.                     }  
  26.                 }  
  27.             }  
  28.         }.start();  
  29.        System.exit(0);  
  30.        }  
  31.  

程序退出機(jī)制選擇

觸發(fā)程序退出的在前面已經(jīng)提到過,但是為了停止方便、安全和優(yōu)雅,一般我們推薦幾種操控性更強(qiáng)的退出機(jī)制。常見的推薦機(jī)制有以下幾種:

1.kill

在linux里用的比較多,向進(jìn)程發(fā)送退出信號(hào),java進(jìn)程收到后平滑退出。

2.shutdownfile

系統(tǒng)創(chuàng)建一個(gè)shutdown file.并監(jiān)聽shutdown file是否存在。如果發(fā)現(xiàn)shutdown file不存在了,那么調(diào)用System.exit,將程序退出。

如果期望只有特定的人才能終止該程序,那么你可以給文件設(shè)定權(quán)限,這樣就只有特定的人可以終止程序。

以下代碼是個(gè)簡(jiǎn)單的例子:

  1. import java.io.File;  
  2. import java.io.IOException;  
  3.  
  4. public class ShutdownFileTest {  
  5.  
  6.     public static void main(String[] args) {  
  7.         // 啟動(dòng)子線程  
  8.         new Thread() {  
  9.  
  10.             public void run() {  
  11.                 while (true) {  
  12.                     try {  
  13.                         Thread.currentThread().sleep(1000);  
  14.                         System.out.println("sub thread is running");  
  15.                     } catch (InterruptedException e) {  
  16.                         e.printStackTrace();  
  17.                     }  
  18.                 }  
  19.             }  
  20.         }.start();  
  21.           
  22.         //啟動(dòng)shutdownfile監(jiān)聽線程  
  23.         new Thread() {  
  24.  
  25.             public void run() {  
  26.                 File shutDownFile = new File("a.shutdown");  
  27.                 // create shut down file  
  28.                 if (!shutDownFile.exists()) {  
  29.                     try {  
  30.                         shutDownFile.createNewFile();  
  31.                     } catch (IOException e) {  
  32.                         e.printStackTrace();  
  33.                     }  
  34.                 }  
  35.                 // watch for file deleted then shutdown   
  36.                 while (true) {  
  37.                     try {  
  38.                         if (shutDownFile.exists()) {  
  39.                             Thread.currentThread().sleep(1000);  
  40.                         } else {  
  41.                             System.exit(0);  
  42.                         }  
  43.                     } catch (InterruptedException e) {  
  44.                         e.printStackTrace();  
  45.                     }  
  46.                 }  
  47.             }  
  48.         }.start();  
  49.     }  
  50.  

3.打開一個(gè)端口,監(jiān)聽端口里的命令,收到命令后調(diào)用System.exit。

這個(gè)似乎不常見,也比較麻煩。

4.JMX

通過JMX的mbean遠(yuǎn)程控制來實(shí)現(xiàn)。

在這個(gè)鏈接里有看到例子:how-to-stop-java-process-gracefully

原文鏈接:http://singleant.iteye.com/blog/1441219

【編輯推薦】

  1. 深入Java探索:Java內(nèi)存區(qū)域
  2. 同一段程序在Java和C中的不同結(jié)果
  3. Java中Runnable和Thread的區(qū)別
  4. Java對(duì)存儲(chǔ)過程的調(diào)用方法
  5. Java初學(xué)者都必須理解的六大問題
責(zé)任編輯:林師授 來源: singleant的博客
相關(guān)推薦

2023-08-14 08:03:25

前端應(yīng)用程序Typescript

2020-12-28 14:40:47

云計(jì)算云應(yīng)用SaaS

2011-10-25 10:24:03

Windows Pho

2010-06-12 16:59:45

UML設(shè)計(jì)

2011-04-11 14:45:41

性能設(shè)計(jì)官方文檔Android

2015-01-06 09:59:59

云應(yīng)用程序Java開發(fā)SQL

2009-09-03 08:46:55

UML類圖Java

2025-03-19 09:04:39

2012-11-15 10:18:11

IBMdw

2012-02-15 14:39:55

GNOME 3

2022-05-04 23:08:36

標(biāo)準(zhǔn)Go應(yīng)用程序

2010-03-04 10:11:17

Android手機(jī)系統(tǒng)

2010-08-12 15:59:23

Flex應(yīng)用程序

2020-03-27 09:20:00

單頁(yè)應(yīng)用程序網(wǎng)頁(yè)設(shè)計(jì)SPAs

2012-04-04 22:10:14

UI

2011-04-01 11:01:02

應(yīng)用程序BlackBerryJava

2009-09-27 10:37:01

Java應(yīng)用程序Hibernate

2012-06-07 09:15:14

ibmdw

2012-05-29 10:04:08

2012-08-01 14:12:45

IBMdW
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)