線上dubbo線程池耗盡CyclicBarrier線程屏障異常解決記錄

事件背景
系統(tǒng)相關(guān)使用人員反饋系統(tǒng)故障,日志顯示從ams系統(tǒng)服務(wù)提示dubbo處理線程不足,具體異常信息如下:

問題定位
從上圖可知,dubbo的處理線程池滿了,默認200個線程,活動線程也是200個。這個現(xiàn)象非常不正常,我們的應(yīng)用并發(fā)還沒有到這個程度能同時占用200個線程處理請求。然后去讀了下dubbo源碼,發(fā)現(xiàn)dubbo也認為這種情況不正常,然后幫我們記錄了應(yīng)用的線程堆棧信息,這個非常贊。代碼如下:

上面這段代碼,在線程池不夠用時,會每隔十分鐘輸出一份dump文件到用戶目錄,如:

在dump文件中,我們找到了耗盡DubboServerHandler線程池最后一個線程

通過分析得知:是我們應(yīng)用程序有段代碼導(dǎo)致的問題,在特定條件下會觸發(fā)線程死鎖,代碼如下

代碼中定義了一個線程屏障CyclicBarrier,同行數(shù)(調(diào)用await的線程數(shù))是11,用來處理十個線程的運算,然后都計算完后拿到處理結(jié)果。本身代碼沒有什么問題,在沒有并發(fā)的情況下,不會觸發(fā)問題。但是注意中間那個箭頭,執(zhí)行線程的線程池是固定大小20的線程池,故當同時并發(fā)數(shù)多于2個的時候線程池的線程會不夠用,導(dǎo)致線程等待,然后CyclicBarrier的main線程也會等待其他線程中的await。這就造成了相互等待,下一個請求過來還是繼續(xù)等待,也就是死鎖了。至此所有問題都以清晰明朗了。
解決問題
方案一:改CyclicBarrier為CountDownLatch,這個兩個并發(fā)工具都是jdk1.5推出為了簡化并發(fā)編程,CyclicBarrier的await會占用線程池中的線程不釋放,導(dǎo)致線程不足,而CountDownLatch的count不會
方案二:改線程池類型為CachedThreadPool,不會應(yīng)為線程池線程不夠用,導(dǎo)致相互等待
文末結(jié)語
java并發(fā)包提供了豐富的api來簡化多線程模型的開發(fā),但是在針對多線程模型業(yè)務(wù)開發(fā)時,我們還需要多留心下多線程帶來的坑??傊嗪藭r代推薦大家多使用多線程開發(fā),同時,也要對使用的工具有更多的了解
以上就是線上dubbo線程池耗盡CyclicBarrier線程屏障異常的詳細內(nèi)容,更多關(guān)于dubbo線程池耗盡CyclicBarrier線程屏障的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring集成MyBatis?及Aop分頁的實現(xiàn)代碼
這篇文章主要介紹了Spring集成MyBatis?及Aop分頁的實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04
淺談Java讀寫注冊表的方式Preferences與jRegistry
這篇文章主要介紹了淺談Java讀寫注冊表的方式Preferences與jRegistry,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-02-02
spring boot微服務(wù)自定義starter原理詳解
這篇文章主要介紹了spring boot微服務(wù)自定義starter原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-12-12
SpringMVC @RequestMapping注解作用詳解
通過@RequestMapping注解可以定義不同的處理器映射規(guī)則,下面這篇文章主要給大家介紹了關(guān)于SpringMVC中@RequestMapping注解用法的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-01-01
java高并發(fā)InterruptedException異常引發(fā)思考
這篇文章主要為大家介紹了java高并發(fā)InterruptedException異常引發(fā)思考,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08

