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

哦,這就是Java的優(yōu)雅停機(jī)?(實(shí)現(xiàn)及原理)

開發(fā) 后端
優(yōu)雅停機(jī)? 這個(gè)名詞我是服的,如果拋開專業(yè)不談,多好的名詞啊!其實(shí)優(yōu)雅停機(jī),就是在要關(guān)閉服務(wù)之前,不是立馬全部關(guān)停,而是做好一些善后操作,比如:關(guān)閉線程、釋放連接資源等。

優(yōu)雅停機(jī)? 這個(gè)名詞我是服的,如果拋開專業(yè)不談,多好的名詞啊!

其實(shí)優(yōu)雅停機(jī),就是在要關(guān)閉服務(wù)之前,不是立馬全部關(guān)停,而是做好一些善后操作,比如:關(guān)閉線程、釋放連接資源等。

再比如,就是不會(huì)讓調(diào)用方的請(qǐng)求處理了一增,一下就中斷了。而處理完本次后,再停止服務(wù)。

Java語(yǔ)言中,我們可以通過(guò)Runtime.getRuntime().addShutdownHook()方法來(lái)注冊(cè)鉤子,以保證程序平滑退出。(其他語(yǔ)言也類似)

來(lái)個(gè)栗子:

  1. public class ShutdownGraceFullTest { 
  2.  
  3.     /** 
  4.      * 使用線程池處理任務(wù) 
  5.      */ 
  6.     public static ExecutorService executorService = Executors.newCachedThreadPool(); 
  7.  
  8.     public static void main(String[] args) { 
  9.  
  10.         //假設(shè)有5個(gè)線程需要執(zhí)行任務(wù) 
  11.         for(int i = 0; i < 5; i++){ 
  12.             final int id = i; 
  13.             Thread taski = new Thread(new Runnable() { 
  14.                 @Override 
  15.                 public void run() { 
  16.                     System.out.println(System.currentTimeMillis() + " : thread_" + id + " start..."); 
  17.                     try { 
  18.                         TimeUnit.SECONDS.sleep(id); 
  19.                     } catch (InterruptedException e) { 
  20.                         e.printStackTrace(); 
  21.                     } 
  22.                     System.out.println(System.currentTimeMillis() + " : thread_" + id + " finish!"); 
  23.                 } 
  24.             }); 
  25.             taski.setDaemon(true); 
  26.             executorService.submit(taski); 
  27.         } 
  28.  
  29.         // 添加一個(gè)鉤子處理未完任務(wù) 
  30.         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
  31.             @Override 
  32.             public void run() { 
  33.  
  34.                 System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No1 shutdown hooking..."); 
  35.                 boolean shutdown = true
  36.                 try { 
  37.                     executorService.shutdown(); 
  38.                     System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() +  " shutdown signal got, wait threadPool finish."); 
  39.                     executorService.awaitTermination(1500, TimeUnit.SECONDS); 
  40.                     System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() +  " all thread's done."); 
  41.                 } 
  42.                 catch (InterruptedException e) { 
  43.                     e.printStackTrace(); 
  44.                 } 
  45.                 System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No1 shutdown done..."); 
  46.             } 
  47.         })); 
  48.  
  49.         // 多個(gè)關(guān)閉鉤子并發(fā)執(zhí)行 
  50.         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
  51.             @Override 
  52.             public void run() { 
  53.                 try { 
  54.                     System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No2 shutdown hooking..."); 
  55.                     Thread.sleep(1000); 
  56.                 } catch (InterruptedException e) { 
  57.                     e.printStackTrace(); 
  58.                 } 
  59.                 System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No2 shutdown done..."); 
  60.             } 
  61.         })); 
  62.  
  63.         System.out.println("main method exit..."); 
  64.         // 故意調(diào)用jvm退出命令,發(fā)送關(guān)閉信號(hào),否則正常情況下 jvm 會(huì)等待***一個(gè)非守護(hù)線程關(guān)閉才會(huì)退出 
  65.         System.exit(0); 
  66.     } 

運(yùn)行結(jié)果如下:

哦,這就是Java的優(yōu)雅停機(jī)?(實(shí)現(xiàn)及原理)

很明顯,確實(shí)是優(yōu)雅了,雖然***收到了一關(guān)閉信號(hào),但是仍然保證了任務(wù)的處理完成。很棒吧!

那么,在實(shí)際應(yīng)用中是如何體現(xiàn)優(yōu)雅停機(jī)呢?

  1. kill -15 pid 

通過(guò)該命令發(fā)送一個(gè)關(guān)閉信號(hào)給到j(luò)vm, 然后就開始執(zhí)行 Shutdown Hook 了,你可以做很多:

  1. 關(guān)閉 socket 鏈接
  2. 清理臨時(shí)文件
  3. 發(fā)送消息通知給訂閱方,告知自己下線
  4. 將自己將要被銷毀的消息通知給子進(jìn)程
  5. 各種資源的釋放
  6. ...

而在平時(shí)工作中,我們不乏看到很多運(yùn)維同學(xué),是這么干的:

  1. kill -9 pid 

如果這么干的話,jvm也無(wú)法了,kill -9 相當(dāng)于一次系統(tǒng)宕機(jī),系統(tǒng)斷電。這會(huì)給應(yīng)用殺了個(gè)措手不及,沒(méi)有留給應(yīng)用任何反應(yīng)的機(jī)會(huì)。

所以,無(wú)論如何是優(yōu)雅不起來(lái)了。

要優(yōu)雅,是代碼

其中,線程池的關(guān)閉方式為:

  1. executorService.shutdown();  
  2. executorService.awaitTermination(1500, TimeUnit.SECONDS); 

ThreadPoolExecutor 在 shutdown 之后會(huì)變成 SHUTDOWN 狀態(tài),無(wú)法接受新的任務(wù),隨后等待正在執(zhí)行的任務(wù)執(zhí)行完成。意味著,shutdown 只是發(fā)出一個(gè)命令,至于有沒(méi)有關(guān)閉還是得看線程自己。

ThreadPoolExecutor 對(duì)于 shutdownNow 的處理則不太一樣,方法執(zhí)行之后變成 STOP 狀態(tài),并對(duì)執(zhí)行中的線程調(diào)用 Thread.interrupt() 方法(但如果線程未處理中斷,則不會(huì)有任何事發(fā)生),所以并不代表“立刻關(guān)閉”。

shutdown() :?jiǎn)?dòng)順序關(guān)閉,其中執(zhí)行先前提交的任務(wù),但不接受新任務(wù)。如果已經(jīng)關(guān)閉,則調(diào)用沒(méi)有附加效果。此方法不等待先前提交的任務(wù)完成執(zhí)行。

shutdownNow():嘗試停止所有正在執(zhí)行的任務(wù),停止等待任務(wù)的處理,并返回正在等待執(zhí)行的任務(wù)的列表。當(dāng)從此方法返回時(shí),這些任務(wù)將從任務(wù)隊(duì)列中耗盡(刪除)。此方法不等待主動(dòng)執(zhí)行的任務(wù)終止。

executor.awaitTermination(this.awaitTerminationSeconds, TimeUnit.SECONDS)); 控制等待的時(shí)間,防止任務(wù)***期的運(yùn)行(前面已經(jīng)強(qiáng)調(diào)過(guò)了,即使是 shutdownNow 也不能保證線程一定停止運(yùn)行)。

注意:

  • 虛擬機(jī)會(huì)對(duì)多個(gè)shutdownhook以未知的順序調(diào)用,都執(zhí)行完后再退出。
  • 如果接收到 kill -15 pid 命令時(shí),執(zhí)行阻塞操作,可以做到等待任務(wù)執(zhí)行完成之后再關(guān)閉 JVM。同時(shí),也解釋了一些應(yīng)用執(zhí)行 kill -15 pid 無(wú)法退出的問(wèn)題,如:中斷被阻塞了,或者h(yuǎn)ook運(yùn)行了死循環(huán)代碼。

 

責(zé)任編輯:未麗燕 來(lái)源: 等你歸去來(lái)
相關(guān)推薦

2024-12-13 16:37:56

SpringBootJava

2025-03-11 00:55:00

Spring停機(jī)安全

2018-11-08 15:30:04

JavaScriptES6異步

2021-05-08 08:33:00

Rocketmq日志數(shù)據(jù)源

2023-01-30 07:41:43

2015-07-21 10:24:02

Windows RT升級(jí)

2014-01-02 14:04:42

2021-09-03 10:44:42

ThreadLocalObject 數(shù)組

2019-01-02 04:40:19

物聯(lián)網(wǎng)企業(yè)IOT

2016-01-12 17:01:45

Bootstrap原因

2015-07-27 10:56:02

2024-03-18 14:06:00

停機(jī)Spring服務(wù)器

2025-03-17 00:00:00

2020-02-17 15:55:22

Office 365

2024-04-24 09:47:36

2015-01-09 10:10:00

Linux

2020-07-17 19:31:19

PythonR編程

2015-09-19 13:45:27

2022-06-08 08:06:05

LinuxJVM內(nèi)存

2022-11-21 16:10:31

奔馳可靠性排名
點(diǎn)贊
收藏

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