成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開發 前端
升級Spring版本到Spring6.2(目前并沒有正式發布),你仍然可以使用6.2.0-SNAPSHOT版本,該版本通過多線程方式初始化Bean對象,這樣就不會出現deadlock問題。

環境:SpringBoot3.2.5

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 ;
  }
}

自定義事件,接收消息及相關數據

1.2 自定義事件監聽

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

該事件監聽器只打印了信息。

1.3 發布事件

@Component
public 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方法等待線程執行完成。

上面的程序運行后,發現輸出了上面的打印內容后應用沒有繼續運行。打印整個線程棧(通過jstack命令查看),如下:

圖片圖片

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

主線程

圖片圖片

主線程創建EventProcessor對象。

Thread-1線程

圖片圖片

Thread-1線程獲取容器中的ApplicationListener類型的bean,該過程將執行到如下步驟:

圖片圖片

main線程持有singletonObjects鎖,Thread-1線程又期望獲取到該鎖,但是main線程還要等待Thread-1線程執行完成。這死鎖了。

以上是對死鎖的復現及原因進行了分析,接下來進行問題的解決。

2. 解決問題

2.1 解決方式1

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

@Component
public 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()) ;
    }
  }
}

這樣改造后容器能正常的啟動,同時事件也正常的發布&監聽。

afterSingletonsInstantiated方法的調用在如下:

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();
      }
    }
  }
}

以上就不會在出現鎖問題。

2.2 解決方式2

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


責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2009-03-13 10:12:18

變量共享匿名方法.NET

2023-02-08 07:04:20

死鎖面試官單元

2024-08-08 09:05:54

2023-04-03 11:23:00

IT 主管首席信息官

2023-11-02 08:10:13

框架Spring程序事件

2011-07-27 10:37:28

IT安全安全錯誤

2024-08-01 09:57:17

DELETE死鎖工具

2024-07-04 00:30:17

2013-01-21 09:41:00

路由器設備故障設置參數

2021-08-12 11:37:23

數據分析錯誤

2011-05-31 15:19:17

2012-06-06 15:38:44

2010-06-07 21:26:22

賽門鐵克諾頓網絡安全

2018-10-16 16:00:39

數據庫鎖舞MySQL

2024-06-03 08:40:31

2021-08-24 08:01:15

死鎖工具多線編程

2021-08-28 09:04:54

死鎖順序鎖輪詢鎖

2024-11-29 16:35:33

解決死鎖Java線程

2016-05-11 10:56:52

數據崇拜

2024-03-27 08:18:02

Spring映射HTML
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品一区二区三区电影 | 午夜在线视频 | 九九热精品视频在线观看 | 亚洲毛片 | 视频三区 | 午夜视频在线免费观看 | 日韩av福利在线观看 | av网站在线看 | 欧美一区二区三区高清视频 | 91xxx在线观看 | 免费看啪啪网站 | 日韩一区中文字幕 | 中文字幕av在线 | 精品国产伦一区二区三区观看方式 | 日韩中出| 青青久视频 | 国产精品黄 | 在线中文视频 | 野狼在线社区2017入口 | 日韩色视频 | 欧美性一区二区三区 | 日韩精品在线看 | 欧美成人高清视频 | 国产亚洲精品久久情网 | 一区二区三区四区免费视频 | 免费在线观看黄色av | 亚洲 欧美 日韩在线 | 不卡的av电影 | 韩日中文字幕 | 91久久国产综合久久 | av免费网站在线 | 男插女下体视频 | 中文字幕成人av | a久久| 国产精品无码专区在线观看 | 中文在线а√在线8 | 国产成人一区二区三区 | 久久精品无码一区二区三区 | 视频一区二区在线观看 | 国产成人91视频 | 国产精品成人一区二区 |