欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

spring容器初始化遇到的死鎖問(wèn)題解決

 更新時(shí)間:2018年07月04日 09:26:19   作者:aitangyong  
這篇文章主要給大家介紹了關(guān)于spring容器初始化時(shí)候遇到的死鎖問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

最近啟動(dòng)spring項(xiàng)目的時(shí)候遇到一個(gè)死鎖問(wèn)題,使用jstack獲取線程堆棧的時(shí)候,可以看到2個(gè)線程出現(xiàn)了死鎖:

解決過(guò)程:

DefaultSingletonBeanRegistry.getSingleton()源碼如下,可以看到這個(gè)方法需要對(duì)singletonObjects加鎖

第二處xxx.subject.core.cache.DataLocalcacheInit.afterPropertiesSet源碼如下:

可以看到:這個(gè)bean在初始化的時(shí)候,會(huì)開(kāi)啟線程,調(diào)用另外一個(gè)bean的initData()方法從數(shù)據(jù)庫(kù)加載數(shù)據(jù)。等數(shù)據(jù)加載完畢,DataLocalcacheInit這個(gè)bean的初始化才算完成。

通過(guò)上面的堆棧可以看出:spring容器在初始化bean的時(shí)候,會(huì)對(duì)singletonObjects對(duì)象加鎖;我們自己在afterPropertiesSet()方法中開(kāi)啟了一個(gè)線程,最終也會(huì)觸發(fā)spring加載另外的bean。第一個(gè)線程(初始化spring的main線程)還沒(méi)有釋放鎖,第二個(gè)線程(自己開(kāi)啟的線程),也需要獲取singletonObjects對(duì)象鎖,這樣就出現(xiàn)了死鎖。表現(xiàn)出來(lái)的現(xiàn)象就是:spring容器卡在那里,不能完成所有bean的初始化。

來(lái)看一段例子,這個(gè)例子和我們項(xiàng)目中實(shí)際代碼很相似。FirstBean調(diào)用ConfigHelper中的方法:

public class FirstBean implements InitializingBean {
 
 @Override
 public void afterPropertiesSet() throws Exception {
  System.out.println("first bean is initializing....");
 
  BlockingQueue queue = new ArrayBlockingQueue(10);
  Thread thread = new Thread() {
 
   @Override
   public void run() {
    ConfigHelper.doSomething();
    queue.add(1);
   }
  };
 
  thread.start();
 
  queue.take();
  System.out.println("first get data....");
 
 }
}

ConfigHelper代碼如下:通過(guò)BeanFactory獲取到另外一個(gè)bean

public class ConfigHelper implements BeanFactoryAware {
 private static BeanFactory factory;
 
 @Override
 public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  this.factory = beanFactory;
 }
 
 public static void doSomething()
 {
  SecondBean bean = (SecondBean)factory.getBean("second");
  bean.say();
 }
}

SecondBean代碼很簡(jiǎn)單如下:

public class SecondBean {
 public void say() {
  System.out.println("SecondBean....");
 }
}

spring配置文件和啟動(dòng)代碼如下,運(yùn)行可以發(fā)現(xiàn)出現(xiàn)死鎖:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">
 
 
 <bean id="config" class="net.aty.spring.deadlock.ConfigHelper"></bean>
 <bean id="first" class="net.aty.spring.deadlock.FirstBean"></bean>
 <bean id="second" class="net.aty.spring.deadlock.SecondBean"></bean>
 
</beans>
public class Main {
 public static void main(String[] args) {
  ApplicationContext context = new FileSystemXmlApplicationContext(
    "src/main/java/net/aty/spring/deadlock/deadlock.xml");// 加載 spring 配置文件
 
 }
}

spring初始化的時(shí)候,如果我們?cè)趕pring提供的一些擴(kuò)展點(diǎn)處(BeanFactoryAware/InitializingBean等),開(kāi)啟線程去獲取bean,很容器出現(xiàn)死鎖。因?yàn)閟pring初始化單例bean(大多數(shù)bean都是單例的)會(huì)加鎖。如果初始化1個(gè)bean的時(shí)候,還沒(méi)有釋放鎖,另一個(gè)線程再次觸發(fā)spring加載bean,就會(huì)出現(xiàn)死鎖。

解決上面的問(wèn)題很簡(jiǎn)單:FirstBean邏輯上是依賴于ConfigHelper和SecondBean的,但是我們卻并沒(méi)有顯示地告訴spring這種邏輯關(guān)系。spring初始化FirstBean的時(shí)候,進(jìn)入afterPropertiesSet() ,這個(gè)方法開(kāi)啟了線程會(huì)觸發(fā)另外2個(gè)bean的加載。我們只要顯示地告訴spring這種依賴關(guān)系,讓spring先加載ConfigHelper和SecondBean就可以了。

<bean id="config" class="net.aty.spring.deadlock.ConfigHelper" depends-on="second"></bean>
<bean id="first" class="net.aty.spring.deadlock.FirstBean" depends-on="config"></bean>
<bean id="second" class="net.aty.spring.deadlock.SecondBean"></bean>

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • 淺談java對(duì)象結(jié)構(gòu) 對(duì)象頭 Markword

    淺談java對(duì)象結(jié)構(gòu) 對(duì)象頭 Markword

    這篇文章主要介紹了淺談java對(duì)象結(jié)構(gòu) 對(duì)象頭 Markword,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • Spring?Validation實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)的示例

    Spring?Validation實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)的示例

    Spring?Validation其實(shí)就是對(duì)Hibernate?Validator進(jìn)一步的封裝,方便在Spring中使用,這篇文章主要介紹了Spring?Validation實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)的示例,需要的朋友可以參考下
    2023-03-03
  • BaseDao封裝JavaWeb的增刪改查的實(shí)現(xiàn)代碼

    BaseDao封裝JavaWeb的增刪改查的實(shí)現(xiàn)代碼

    Basedao 是一種基于數(shù)據(jù)訪問(wèn)對(duì)象(Data Access Object)模式的設(shè)計(jì)方法,它是一個(gè)用于處理數(shù)據(jù)庫(kù)操作的基礎(chǔ)類(lèi),負(fù)責(zé)封裝數(shù)據(jù)庫(kù)訪問(wèn)的底層操作,提供通用的數(shù)據(jù)庫(kù)訪問(wèn)方法,本文給大家介紹了BaseDao封裝JavaWeb的增刪改查的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2024-03-03
  • 聊聊如何在springboot中添加模版

    聊聊如何在springboot中添加模版

    本文,我們談?wù)勅绾卧?nbsp;spring boot 中添加模版,因?yàn)橛袝r(shí)候我們也是需要后端渲染的嘛,比如公司官網(wǎng),文中有詳細(xì)的代碼示例供我們參考,需要的朋友可以參考下
    2023-08-08
  • Java中ArrayList實(shí)現(xiàn)原理及基本方法

    Java中ArrayList實(shí)現(xiàn)原理及基本方法

    這篇文章主要介紹了Java中ArrayList實(shí)現(xiàn)原理及基本方法,ArrayList是開(kāi)發(fā)中非常常用的數(shù)據(jù)存儲(chǔ)容器之一,其底層是數(shù)組實(shí)現(xiàn)的,我們可以在集合中存儲(chǔ)任意類(lèi)型的數(shù)據(jù),ArrayList是線程不安全的,擅長(zhǎng)隨機(jī)訪問(wèn)元素,插入和刪除較慢,需要的朋友可以參考下
    2023-08-08
  • SSH框架網(wǎng)上商城項(xiàng)目第19戰(zhàn)之訂單信息級(jí)聯(lián)入庫(kù)以及頁(yè)面緩存問(wèn)題

    SSH框架網(wǎng)上商城項(xiàng)目第19戰(zhàn)之訂單信息級(jí)聯(lián)入庫(kù)以及頁(yè)面緩存問(wèn)題

    這篇文章主要介紹了SSH框架網(wǎng)上商城項(xiàng)目第19戰(zhàn)之訂單信息級(jí)聯(lián)入庫(kù)以及頁(yè)面緩存問(wèn)題,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Java中方法重寫(xiě)與重載的區(qū)別

    Java中方法重寫(xiě)與重載的區(qū)別

    大家好,本篇文章主要講的是Java中方法重寫(xiě)與重載的區(qū)別,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • C++ 程序流程結(jié)構(gòu)詳解

    C++ 程序流程結(jié)構(gòu)詳解

    這篇文章主要介紹了C++程序的程序流程結(jié)構(gòu)以及關(guān)系和邏輯運(yùn)算符講解,是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2021-09-09
  • Spring中ApplicationEvent事件機(jī)制源碼詳解

    Spring中ApplicationEvent事件機(jī)制源碼詳解

    這篇文章主要介紹了Spring中ApplicationEvent事件機(jī)制源碼詳解,Spring中與事件有關(guān)的接口和類(lèi)主要包括ApplicationEvent、ApplicationListener,下面來(lái)看一下Spring中事件的具體應(yīng)用,需要的朋友可以參考下
    2023-09-09
  • Log4j不同模塊輸出到不同的文件中

    Log4j不同模塊輸出到不同的文件中

    這篇文章主要介紹了Log4j不同模塊輸出到不同的文件中 的相關(guān)資料,需要的朋友可以參考下
    2016-08-08

最新評(píng)論