日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

警惕!SpringBoot錯誤發布事件,造成死鎖Deadlock

來源: 責編: 時間:2024-06-12 08:43:40 144觀看
導讀環境:SpringBoot3.2.51. 死鎖復現1.1 自定義事件監聽public class PackApplicationEvent extends ApplicationEvent { private String message ; public PackApplicationEvent(String message, Object source) {

環境:SpringBoot3.2.5CtR28資訊網——每日最新資訊28at.com

1. 死鎖復現

1.1 自定義事件監聽

public class PackApplicationEvent extends ApplicationEvent {  private String message ;  public PackApplicationEvent(String message, Object source) {    super(source) ;    this.message = message ;  }  public String getMessage() {    return message ;  }}

自定義事件,接收消息及相關數據CtR28資訊網——每日最新資訊28at.com

1.2 自定義事件監聽

@Componentpublic class PackApplicationListener implements ApplicationListener<PackApplicationEvent> {  @Override  public void onApplicationEvent(PackApplicationEvent event) {    System.out.printf("接收到事件消息: %s, 數據: %s%n", event.getMessage(), event.getSource().toString()) ;    // TODO  }}

該事件監聽器只打印了信息。CtR28資訊網——每日最新資訊28at.com

1.3 發布事件

@Componentpublic class EventProcessor {  public EventProcessor(ApplicationEventPublisher eventPublisher) {    Thread t = new Thread(() -> {      eventPublisher.publishEvent(new PackApplicationEvent("自定義事件", EventProcessor.this));    });    t.start() ;    try {      System.out.println("線程啟動,等待執行完成...") ;      t.join() ;    } catch (InterruptedException e) {      System.err.printf("線程中斷: %s, 錯誤: %s%n", Thread.currentThread().getName(), e.getMessage()) ;    }  }}

該Bean在構造函數中新啟一個線程發布事件,同時通過join方法等待線程執行完成。CtR28資訊網——每日最新資訊28at.com

上面的程序運行后,發現輸出了上面的打印內容后應用沒有繼續運行。打印整個線程棧(通過jstack命令查看),如下:CtR28資訊網——每日最新資訊28at.com

圖片圖片CtR28資訊網——每日最新資訊28at.com

根據線程信息,main線程在創建EventProcessor對象時,會先持有DefaultSingletonBeanRegistry.singletonObjects這個ConcurrentHashMap對象鎖接著創建EventProcessor對象實例,在調用該對象的構造函數時,啟動新的線程Thread-1,該線程發布事件同時通過join方法等待T1這個線程完成,在發布事件時Spring容器會獲取所有的ApplicationListener,此時就會又創建PackApplicationListener對象,創建該對象同樣要獲取singletonObjects鎖對象,這樣就造成了死鎖。CtR28資訊網——每日最新資訊28at.com

主線程

圖片圖片CtR28資訊網——每日最新資訊28at.com

主線程創建EventProcessor對象。CtR28資訊網——每日最新資訊28at.com

Thread-1線程

圖片圖片CtR28資訊網——每日最新資訊28at.com

Thread-1線程獲取容器中的ApplicationListener類型的bean,該過程將執行到如下步驟:CtR28資訊網——每日最新資訊28at.com

圖片圖片CtR28資訊網——每日最新資訊28at.com

main線程持有singletonObjects鎖,Thread-1線程又期望獲取到該鎖,但是main線程還要等待Thread-1線程執行完成。這死鎖了。CtR28資訊網——每日最新資訊28at.com

以上是對死鎖的復現及原因進行了分析,接下來進行問題的解決。CtR28資訊網——每日最新資訊28at.com

2. 解決問題

2.1 解決方式1

不要在構造函數中發布事件,而是應該在所有的單例對象都創建完后再執行,也就是實現SmartInitializingSingleton接口,該接口對應的回調方法會在所有的單例bean都創建完以后執行,這樣就不會再出現deadlock問題。CtR28資訊網——每日最新資訊28at.com

@Componentpublic class EventProcessor implements SmartInitializingSingleton {  private final ApplicationEventPublisher eventPublisher ;  public EventProcessor(ApplicationEventPublisher eventPublisher) {    this.eventPublisher = eventPublisher ;  }  @Override  public void afterSingletonsInstantiated() {    Thread t = new Thread(() -> {      eventPublisher.publishEvent(new PackApplicationEvent("自定義事件", EventProcessor.this));    });    t.start() ;    try {      t.join() ;    } catch (InterruptedException e) {      System.err.printf("線程中斷: %s, 錯誤: %s%n", Thread.currentThread().getName(), e.getMessage()) ;    }  }}

這樣改造后容器能正常的啟動,同時事件也正常的發布&監聽。CtR28資訊網——每日最新資訊28at.com

afterSingletonsInstantiated方法的調用在如下:CtR28資訊網——每日最新資訊28at.com

public class DefaultListableBeanFactory {  public void preInstantiateSingletons() {    for (String beanName : beanNames) {      // 創建單例bean      getBean(beanName);    }    // 單例bean創建完成以后,執行afterSingletonsInstantiated回調方法    for (String beanName : beanNames) {      Object singletonInstance = getSingleton(beanName);      if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {        smartSingleton.afterSingletonsInstantiated();      }    }  }}

以上就不會在出現鎖問題。CtR28資訊網——每日最新資訊28at.com

2.2 解決方式2

升級Spring版本到Spring6.2(目前并沒有正式發布),你仍然可以使用6.2.0-SNAPSHOT版本,該版本通過多線程方式初始化Bean對象,這樣就不會出現deadlock問題。CtR28資訊網——每日最新資訊28at.com


CtR28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-93206-0.html警惕!SpringBoot錯誤發布事件,造成死鎖Deadlock

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 聊聊 Mybatis 動態 SQL

下一篇: 網易面試:SpringBoot如何開啟虛擬線程?

標簽:
  • 熱門焦點
  • Find N3入網:最高支持16+1TB

    OPPO將于近期登場的Find N3折疊屏目前已經正式入網,型號為PHN110。本次Find N3在外觀方面相比前兩代有很大的變化,不再是小號的橫向折疊屏,而是跟別的廠商一樣采用了較為常見的
  • 如何正確使用:Has和:Nth-Last-Child

    我們可以用CSS檢查,以了解一組元素的數量是否小于或等于一個數字。例如,一個擁有三個或更多子項的grid。你可能會想,為什么需要這樣做呢?在某些情況下,一個組件或一個布局可能會
  • 學習JavaScript的10個理由...

    作者 | Simplilearn編譯 | 王瑞平當你決心學習一門語言的時候,很難選擇到底應該學習哪一門,常用的語言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 量化指標是與非:挽救被量化指標扼殺的技術團隊

    作者 | 劉新翠整理 | 徐杰承本文整理自快狗打車技術總監劉新翠在WOT2023大會上的主題分享,更多精彩內容及現場PPT,請關注51CTO技術棧公眾號,發消息【WOT2023PPT】即可直接領取
  • 19個 JavaScript 單行代碼技巧,讓你看起來像個專業人士

    今天這篇文章跟大家分享18個JS單行代碼,你只需花幾分鐘時間,即可幫助您了解一些您可能不知道的 JS 知識,如果您已經知道了,就當作復習一下,古人云,溫故而知新嘛。現在,我們就開始今
  • 破圈是B站頭上的緊箍咒

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之每年的暑期檔都少不了瞄準追劇女孩們的古偶劇集,2021年有優酷的《山河令》,2022年有愛奇藝的《蒼蘭訣》,今年卻輪到小破站抓住了追
  • 華為HarmonyOS 4.0將于8月4日發布 或搭載AI大模型技術

    華為宣布HarmonyOS4.0將于8月4日正式發布。此前,華為已經針對開發者公布了HarmonyOS4.0,以便于開發者提前進行適配,也因此被曝光出了一些新系統的特性
  • iQOO Neo8系列或定檔5月23日:首發天璣9200+ 安卓跑分王者

    去年10月,iQOO推出了iQOO Neo7系列機型,不僅搭載了天璣9000+,而且是同價位唯一一款天璣9000+直屏旗艦,一經上市便受到了用戶的廣泛關注。在時隔半年后,
  • 與兆芯合作 聯想推出全新旗艦版筆記本電腦開天N7系列

    聯想與兆芯合作推出全新聯想旗艦版筆記本電腦開天 N7系列。這個系列采用兆芯KX-6640MA處理器平臺,KX-6640MA 處理器是采用了陸家嘴架構,16nm 工藝,4 核 4 線
Top 主站蜘蛛池模板: 民丰县| 海安县| 东丽区| 鸡泽县| 德钦县| 库尔勒市| 阿尔山市| 阿荣旗| 金昌市| 米脂县| 隆回县| 东海县| 栾川县| 石河子市| 梧州市| 济南市| 湟源县| 连云港市| 独山县| 阿荣旗| 阳曲县| 阳山县| 灵武市| 讷河市| 宁陵县| 瑞丽市| 晋州市| 奎屯市| 灵武市| 宣威市| 当雄县| 阳江市| 广宁县| 涪陵区| 宣汉县| 兴业县| 江门市| 法库县| 卢龙县| 洛隆县| 库伦旗|