日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ActiveMQ消费者平滑关闭

發(fā)布時(shí)間:2024/7/23 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ActiveMQ消费者平滑关闭 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

平滑關(guān)閉的思路就是讓正在執(zhí)行的任務(wù)線程正常執(zhí)行完畢,然后再關(guān)閉JVM。在JVM關(guān)閉之前觸發(fā)一個(gè)shutdown hook,jvm自帶這個(gè)hook,在java啟動(dòng)時(shí)候就可以注冊這樣的hook。

##1、簡述JVM關(guān)閉鉤子(shutdown hook) 首先JVM的關(guān)閉方式可以分為三種:

  • 正常關(guān)閉:當(dāng)最后一個(gè)非守護(hù)線程結(jié)束或者調(diào)用了System.exit或者通過其他特定平臺(tái)的方法關(guān)閉(發(fā)送SIGINT,SIGTERM信號(hào)等)

  • 強(qiáng)制關(guān)閉:通過調(diào)用Runtime.halt方法或者是在操作系統(tǒng)中直接kill(發(fā)送SIGKILL信號(hào))掉JVM進(jìn)程

  • 異常關(guān)閉:運(yùn)行中遇到RuntimeException異常等。

在某些情況下,我們需要在JVM關(guān)閉時(shí)做些掃尾的工作,比如刪除臨時(shí)文件、停止日志服務(wù)以及內(nèi)存數(shù)據(jù)寫到磁盤等,為此JVM提供了關(guān)閉鉤子(shutdown hooks)來做這些事情。另外特別注意的是:如果JVM因異常關(guān)閉,那么子線程(Hook本質(zhì)上也是子線程)將不會(huì)停止。但在JVM被強(qiáng)行關(guān)閉時(shí),這些線程都會(huì)被強(qiáng)行結(jié)束。

另外在使用關(guān)閉鉤子還要注意以下幾點(diǎn):

  • 不能在鉤子調(diào)用System.exit(),否則卡住JVM的關(guān)閉過程,但是可以調(diào)用Runtime.halt()。
  • 不能再鉤子中再進(jìn)行鉤子的添加和刪掉操作,否則將會(huì)拋出IllegalStateException。
  • 在System.exit()之后添加的鉤子無效。
  • 當(dāng)JVM收到SIGTERM命令(比如操作系統(tǒng)在關(guān)閉時(shí))后,如果鉤子線程在一定時(shí)間沒有完成,那么Hook線程可能在執(zhí)行過程中被終止。
  • Hook線程中同樣會(huì)拋出異常,如果拋出異常又不處理,那么鉤子的執(zhí)行序列就會(huì)被停止。
  • ##2、 ActiveMQ消費(fèi)者的鉤子

    先講一下我的消費(fèi)者整體情況:

    1、使用Spring集成ActiveMQ,用Spring容器進(jìn)行bean的管理

    2、用DefaultMessageListenerContainer來監(jiān)聽處理隊(duì)列里的消息

    直接貼代碼:

    //消費(fèi)者是普通的java工程,通過這個(gè)類的main方法啟動(dòng),這里只貼出main函數(shù)里的代碼 public static void main( String[] args ) {log.info("start APP......");ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");//testContainer是在配置文件中配置的監(jiān)聽器final DefaultMessageListenerContainer container = (DefaultMessageListenerContainer)context.getBean("testContainer");Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {public void run() {System.out.println("-------------------- 消費(fèi)者JVM即將關(guān)閉,執(zhí)行清場操作 --------------------");//關(guān)閉線程池,等待線程池積壓消息處理container.shutdown();System.out.println("-------------------- 消費(fèi)者關(guān)閉,線程池處理完畢 --------------------");//不要在鉤子里面執(zhí)行System.exit,調(diào)用halt()是可以正常關(guān)閉系統(tǒng)的,但是貌似沒這個(gè)必要//Runtime.getRuntime().halt(0);}})); }

    為了可以更直觀的看到這個(gè)等待任務(wù)線程處理完的一個(gè)過程,在任務(wù)線程里添加sleep代碼。

    public class TestMessageListener implements SessionAwareMessageListener {public void onMessage(Message message, Session session) {if (message instanceof TextMessage) {TextMessage textMsg = (TextMessage) message;try {Thread.sleep(1000L);System.out.println(Thread.currentThread().getName() + ",接收到一個(gè)純文本消息,消息內(nèi)容是:" + textMsg.getText());} catch (JMSException e) {e.printStackTrace();}catch (InterruptedException e) {e.printStackTrace();}}} }

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

    ##3、 關(guān)閉消費(fèi)者

    關(guān)閉消費(fèi)者的時(shí)候也很重要,不要使用kill -9的方式來殺進(jìn)程,這是無腦殺。

    ref:

    • 深入JVM關(guān)閉與關(guān)閉鉤子
    • JAVA虛擬機(jī)關(guān)閉鉤子(Shutdown Hook)
    • Java消息隊(duì)列任務(wù)的平滑關(guān)閉
    • 使用后臺(tái)進(jìn)程和 Shutdown Hook 友好地關(guān)閉 Tomcat
    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的ActiveMQ消费者平滑关闭的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。