美團三面:一個線程OOM,進程里其他線程還能運行麼

點擊上方"java全棧技術"關注,每天學習一個java知識點

出自今年校招美團三面的一個真題。大致如下

一個進程有3個線程,如果一個線程拋出oom,其他兩個線程還能運行麼?

先說一下答案,答案是還能運行

不瞞大家說,真在面試中,我遇到這一題,我估計也是答錯。因為我初看到這一題,內心嘿嘿一笑,覺得這題是在考察JVM的內存結構。我第一反應是OOM的常見情況堆溢出,也就是下面的這種異常

java.lang.OutOfMemoryError: Java heap space

先回憶一下,多線程中棧與堆是公有的還是私有的?回答如下

在多線程環境下,每個線程擁有一個棧和一個程序計數器。棧和程序計數器用來保存線程的執行歷史和線程的執行狀態,是線程私有的資源。其他的資源(比如堆、地址空間、全局變量)是由同一個進程內的多個線程共享。

也就是說,堆是線程共享。那麼一個線程堆拋出OOM異常,我第一反應是另外兩個線程也拋出OOM異常,畢竟堆是共有的,大家應該都拋出異常。於是,我機智的寫個代碼去測試一下,結果我被啪啪啪打臉了。 測試代碼偽如下 一個線程去構造堆溢出,每隔1S申請一次堆,代碼長下面這樣

美團三面:一個線程OOM,進程裡其他線程還能運行麼


另一個線程,睡眠1秒然後輸出就好,代碼長下面這樣

美團三面:一個線程OOM,進程裡其他線程還能運行麼


結果,輸出是長下面這樣的

美團三面:一個線程OOM,進程裡其他線程還能運行麼


大家發現了麼,一個線程溢出了,其他線程還在跑,這好像和我們的認知不大一樣。坦白說,我看到這個結果,瞬間覺得自己一世英名毀於一旦,從此無法抬起頭來做人。沒辦法了,只能亮出工具來看一下了。 先說一下,在本例測試中,參數如下 -Xms16m -Xmx32m-Xms 初始堆內存 -Xmx 最大堆內存

接下來,亮出 JvisualVM看堆的變化,注意看上面那張圖,拋出OOM的時間約在00:11:45左右,因此我們需要重點關注 00:11:45左右的曲線變化,如下圖所示

美團三面:一個線程OOM,進程裡其他線程還能運行麼

如圖所示,我們仔細觀察一下在 00:11:44~ 00:11:45之間曲線變化,你會發現使用堆的數量,突然間急劇下滑!這代表著一點,當一個線程拋出OOM異常後,它所佔據的內存資源會全部被釋放掉,從而不會影響其他線程的運行! 講到這裡大家應該懂了,此題的答案為

一個線程溢出後,進程裡的其他線程還能照常運行。注意了,這個例子我只演示了堆溢出的情況。如果是棧溢出,結論也是一樣的,大家可自行通過代碼測試。

補充:OOM發生時如果程序能正常處理這個異常情況,比如不再申請更多的內存或其它資源,或者放棄那個子任務或子線程,系統OOM狀態是可以回到正常情況


分享到:


相關文章: