天天看點

兩種思路解決線程服務死循環

背景

系統突然error飚高,不停full gc。

最後發現是因為調用的外部jar包中方法觸發bug導緻死循環,不斷産生新對象,導緻記憶體大量占用無法釋放,最終jvm記憶體回收機制崩潰。

解決思路

服務一旦進入死循環,對應線程一直處于running狀态,難以通過該線程自己計時中斷。

對于無法完全放心的第三方jar包方法,可以選擇開子線程處理,并對線程加以監控,當逾時時及時中斷子線程并傳回。

兩種實作思路:

思路一: 通過futuretask

    future在設定的時間逾時後會抛出timeout異常,通常做法是捕獲異常後執行future.cancel()方法。但cancel方法實際是調用線程的interrupt方法,給線程樹立interrupt status,并不能中斷死循環的子線程。

兩種思路解決線程服務死循環

future沒有提供能夠直接停止子線程的方法(也許是因為線程的stop方法可能産生不良後果)

是以這裡可以參照futuretask源碼,建立一個myfuturetask類,改寫或建立一個類似cancel的方法,調用線程的stop方法。

demo中的myfuturetask類參考cancel方法,建立了myfuturetask.stop方法,調用子線程的stop方法來中止子線程。

思路二:通過countdownlatch

    主線程建立可能出現死循環的子線程時設立countdownlatch值為1,子線程邏輯中當處理完畢執行countdownlatch減1。這樣主線程可以看到子線程是執行完畢還是逾時,如果逾時或子線程已處理完畢,在主線程中執行子線程的stop方法中止子線程。

demo代碼

思路一:

思路二: