<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 4431字,需瀏覽 9分鐘

           ·

          2020-11-30 22:34

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

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

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

          Java語言中,我們可以通過

          Runtime.getRuntime().addShutdownHook()

          方法來注冊鉤子,以保證程序平滑退出。(其他語言也類似)?

          來個栗子:

          1. publicclassShutdownGraceFullTest {

          2. ? ?/**

          3. ? ? * 使用線程池處理任務(wù)

          4. ? ? */

          5. ? ?publicstaticExecutorService executorService = Executors.newCachedThreadPool();

          6. ? ?publicstaticvoid main(String[] args) {

          7. ? ? ? ?//假設(shè)有5個線程需要執(zhí)行任務(wù)

          8. ? ? ? ?for(int i = 0; i < 5; i++){

          9. ? ? ? ? ? ?finalint id = i;

          10. ? ? ? ? ? ?Thread taski = newThread(newRunnable() {

          11. ? ? ? ? ? ? ? ?@Override

          12. ? ? ? ? ? ? ? ?publicvoid run() {

          13. ? ? ? ? ? ? ? ? ? ?System.out.println(System.currentTimeMillis() + " : thread_" + id + " start...");

          14. ? ? ? ? ? ? ? ? ? ?try {

          15. ? ? ? ? ? ? ? ? ? ? ? ?TimeUnit.SECONDS.sleep(id);

          16. ? ? ? ? ? ? ? ? ? ?} catch (InterruptedException e) {

          17. ? ? ? ? ? ? ? ? ? ? ? ?e.printStackTrace();

          18. ? ? ? ? ? ? ? ? ? ?}

          19. ? ? ? ? ? ? ? ? ? ?System.out.println(System.currentTimeMillis() + " : thread_" + id + " finish!");

          20. ? ? ? ? ? ? ? ?}

          21. ? ? ? ? ? ?});

          22. ? ? ? ? ? ?taski.setDaemon(true);

          23. ? ? ? ? ? ?executorService.submit(taski);

          24. ? ? ? ?}

          25. ? ? ? ?// 添加一個鉤子處理未完任務(wù)

          26. ? ? ? ?Runtime.getRuntime().addShutdownHook(newThread(newRunnable() {

          27. ? ? ? ? ? ?@Override

          28. ? ? ? ? ? ?publicvoid run() {

          29. ? ? ? ? ? ? ? ?System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No1 shutdown hooking...");

          30. ? ? ? ? ? ? ? ?boolean shutdown = true;

          31. ? ? ? ? ? ? ? ?try {

          32. ? ? ? ? ? ? ? ? ? ?executorService.shutdown();

          33. ? ? ? ? ? ? ? ? ? ?System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + ?" shutdown signal got, wait threadPool finish.");

          34. ? ? ? ? ? ? ? ? ? ?executorService.awaitTermination(1500, TimeUnit.SECONDS);

          35. ? ? ? ? ? ? ? ? ? ?System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + ?" all thread's done.");

          36. ? ? ? ? ? ? ? ?}

          37. ? ? ? ? ? ? ? ?catch (InterruptedException e) {

          38. ? ? ? ? ? ? ? ? ? ?e.printStackTrace();

          39. ? ? ? ? ? ? ? ?}

          40. ? ? ? ? ? ? ? ?System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No1 shutdown done...");

          41. ? ? ? ? ? ?}

          42. ? ? ? ?}));

          43. ? ? ? ?// 多個關(guān)閉鉤子并發(fā)執(zhí)行

          44. ? ? ? ?Runtime.getRuntime().addShutdownHook(newThread(newRunnable() {

          45. ? ? ? ? ? ?@Override

          46. ? ? ? ? ? ?publicvoid run() {

          47. ? ? ? ? ? ? ? ?try {

          48. ? ? ? ? ? ? ? ? ? ?System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No2 shutdown hooking...");

          49. ? ? ? ? ? ? ? ? ? ?Thread.sleep(1000);

          50. ? ? ? ? ? ? ? ?} catch (InterruptedException e) {

          51. ? ? ? ? ? ? ? ? ? ?e.printStackTrace();

          52. ? ? ? ? ? ? ? ?}

          53. ? ? ? ? ? ? ? ?System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No2 shutdown done...");

          54. ? ? ? ? ? ?}

          55. ? ? ? ?}));

          56. ? ? ? ?System.out.println("main method exit...");

          57. ? ? ? ?// 故意調(diào)用jvm退出命令,發(fā)送關(guān)閉信號,否則正常情況下 jvm 會等待最后一個非守護線程關(guān)閉才會退出

          58. ? ? ? ?System.exit(0);

          59. ? ?}

          60. }

          運行結(jié)果如下:

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

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

          1. kill -15 pid

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

          1、 關(guān)閉 socket 鏈接

          2、 清理臨時文件

          3、 發(fā)送消息通知給訂閱方,告知自己下線

          4、 將自己將要被銷毀的消息通知給子進程

          5、 各種資源的釋放

          ...

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

          1. kill -9 pid

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

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

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

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

          1. executorService.shutdown();

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

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

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

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

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

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

          注意:

          虛擬機會對多個shutdownhook以未知的順序調(diào)用,都執(zhí)行完后再退出。

          如果接收到 kill -15 pid 命令時,執(zhí)行阻塞操作,可以做到等待任務(wù)執(zhí)行完成之后再關(guān)閉 JVM。同時,也解釋了一些應(yīng)用執(zhí)行 kill -15 pid 無法退出的問題,如:中斷被阻塞了,或者h(yuǎn)ook運行了死循環(huán)代碼。

          出處:https://dwz.cn/nRS7c1Zg



          —————END—————

          更多精彩:
          Java實戰(zhàn)項目視頻,給需要的讀者,收藏!
          27個阿里 Java 開源項目,值得收藏!
          從0到1搭建后端架構(gòu)的經(jīng)歷
          Spring Boot 注解大全,一鍵收藏!
          差點被開除:一次訂單號重復(fù)的事故!
          一款仿網(wǎng)易云音樂Java開源系統(tǒng)(附源碼)

          關(guān)注公眾號,查看更多優(yōu)質(zhì)文章

          最近,整理一份Java資料Java從0到1,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
          獲取方式:關(guān)注公眾號并回復(fù)?Java?領(lǐng)取,更多Java內(nèi)容陸續(xù)奉上。
          明天見(??ω??)??

          瀏覽 55
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产成人无码区免费视频 | 91精品国产91久久久久久久久久 | 国内稀有盗摄偷窥盗摄Av | 国内三级在线 | 久久久久久国产精品三级玉女聊斋 |