再不解決延遲不當,小心你的內存被打爆


摘要:這是在具體代碼中發現的不當延遲的問題,極端情況下可能把內存打爆。

本文分享自華為雲社區《線程中不當使用延遲問題》,原文作者:技術火炬手 。

背景

這是在具體代碼中發現的不當延遲的問題,極端情況下可能把內存打爆。

代碼DevLicenseServiceRoaDelegateImpl.java

定義:

image002.jpg

使用:

image004.jpg

signalRefreshHelp 定義

image006.jpg

這段代碼最大問題是使用延遲算法不當,在極端情況下會導致內存暴漲,嚴重影響服務程序的性能。

不要使用sleep來實現延遲

使用sleep實現延遲看起來非常直觀,但是這個在高並發、多請求、長期運行的服務程序里必須特別小心。這是因為衡量服務程序性能的一個非常重要的指標是QPS, 就是服務程序的處理能力,一般情況下越大越好;服務程序的總並發能力等於每個線程的qps;單個線程的QPS = 1000毫秒 / (處理一個請求的毫秒);所以上面那個線程的QPS <= 1000 / 10000 = 0.1 (因為線程sleep了10000毫秒)。

這里的處理邏輯是錯誤的!也有很嚴重的性能隱患,不過幸好調用這個api 請求不多,才沒有導致嚴重問題。

開發者的意圖是在創建一個任務后,延遲10s執行該任務,處理時序圖如下

image008.jpg

假如時間點t1 & t2 挨得很接近的話,線程在執行job1 & job2 也是很接近。

但實際的情況變成:

image010.jpg

就算創建job1 & job2的時間很接近,但job2執行的時間會比預期多了10s;連續提交的任務越多,越容易堆積,這些堆積的任務存放在 blocking queue,一直到處理完畢才刪除;如果這類請求很多的話,很容易引起內存爆掉。

解決方案

選擇合適的數據結構,默認線程池關聯的隊列是LinkedBlockingQueue , 沒有延遲控制,可以使用DelayQueue

image012.jpg

DelayQueue內部使用了PriorityQueue 按時間排序;需要自己使用Delayed 接口封裝請求數據

下面是例子

image014.jpg

測試代碼,同時加入 3個需要延遲10s的任務

image016.jpg

測試結果:

image018.jpg

符合預期

 

點擊關注,第一時間了解華為雲新鮮技術~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM