小編給大家分享一下如何解決spring容器初始化遇到的死鎖問題,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
成都創(chuàng)新互聯(lián)服務(wù)項目包括神池網(wǎng)站建設(shè)、神池網(wǎng)站制作、神池網(wǎng)頁制作以及神池網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,神池網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到神池省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!前言
最近啟動spring項目的時候遇到一個死鎖問題,使用jstack獲取線程堆棧的時候,可以看到2個線程出現(xiàn)了死鎖:
解決過程:
DefaultSingletonBeanRegistry.getSingleton()
源碼如下,可以看到這個方法需要對singletonObjects加鎖
第二處xxx.subject.core.cache.DataLocalcacheInit.afterPropertiesSet源碼如下:
可以看到:這個bean在初始化的時候,會開啟線程,調(diào)用另外一個bean的initData()
方法從數(shù)據(jù)庫加載數(shù)據(jù)。等數(shù)據(jù)加載完畢,DataLocalcacheInit這個bean的初始化才算完成。
通過上面的堆??梢钥闯觯簊pring容器在初始化bean的時候,會對singletonObjects對象加鎖;我們自己在afterPropertiesSet()
方法中開啟了一個線程,最終也會觸發(fā)spring加載另外的bean。第一個線程(初始化spring的main線程)還沒有釋放鎖,第二個線程(自己開啟的線程),也需要獲取singletonObjects對象鎖,這樣就出現(xiàn)了死鎖。表現(xiàn)出來的現(xiàn)象就是:spring容器卡在那里,不能完成所有bean的初始化。
來看一段例子,這個例子和我們項目中實際代碼很相似。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代碼如下:通過BeanFactory獲取到另外一個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代碼很簡單如下:
public class SecondBean { public void say() { System.out.println("SecondBean...."); } }
spring配置文件和啟動代碼如下,運行可以發(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初始化的時候,如果我們在spring提供的一些擴展點處(BeanFactoryAware/InitializingBean等),開啟線程去獲取bean,很容器出現(xiàn)死鎖。因為spring初始化單例bean(大多數(shù)bean都是單例的)會加鎖。如果初始化1個bean的時候,還沒有釋放鎖,另一個線程再次觸發(fā)spring加載bean,就會出現(xiàn)死鎖。
解決上面的問題很簡單:FirstBean邏輯上是依賴于ConfigHelper和SecondBean的,但是我們卻并沒有顯示地告訴spring這種邏輯關(guān)系。spring初始化FirstBean的時候,進入afterPropertiesSet()
,這個方法開啟了線程會觸發(fā)另外2個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>
以上是“如何解決spring容器初始化遇到的死鎖問題”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
本文題目:如何解決spring容器初始化遇到的死鎖問題-創(chuàng)新互聯(lián)
網(wǎng)頁地址:http://www.rwnh.cn/article34/ceiepe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗、企業(yè)網(wǎng)站制作、靜態(tài)網(wǎng)站、標簽優(yōu)化、品牌網(wǎng)站設(shè)計、做網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)