美團面試真題之一個線程OOM,進程裡的其他線程還能運行嗎?

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

答案是還能運行

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

<code>

java

.lang

.OutOfMemoryError

java

heap

space

/<code>

多線程中棧與堆是公有還是私有的

<code>在多線程環境下,每個線程擁有一個棧和一個程序計數器,棧和程序計數器用來保存線程執行歷史和線程執行狀態,是線程私有的,堆是由用一個進程內多個線程共享的。
/<code>

測試代碼偽代碼如下:

一個線程去構造堆內存溢出,每隔ls申請一次堆內存。

<code>

package

com.ypb.oom;

import

com.google.common.collect.Lists;

import

java.time.LocalDateTime;

import

java.time.format.DateTimeFormatter;

import

java.util.List;

import

java.util.concurrent.Executors;

import

java.util.concurrent.TimeUnit;

import

lombok.extern.slf4j.Slf4j; 4j

public

class

ThreadOOMTest

{

public

static

void

main

(String[] args)

{ DateTimeFormatter formatter = DateTimeFormatter.ofPattern(

"yyyy-MM-dd HH:mm:ss"

);

int

m =

1024

*

1024

; String name =

"oom-thread"

;

new

Thread(() -> { List<

byte

[]> bytes = Lists.newArrayList();

while

(

true

) { show(format(formatter)); bytes.add(

new

byte

[m]); sleep(); } }, name).start(); name =

"not-oom-thread"

;

new

Thread(()->{

while

(

true

) { show(format(formatter)); sleep(); } }, name).start(); }

private

static

void

show

(String msg)

{ System.out.println(msg); }

private

static

void

sleep

()

{

try

{ TimeUnit.SECONDS.sleep(

1L

); }

catch

(Exception e) { e.printStackTrace(); } }

private

static

String

format

(DateTimeFormatter formatter)

{

return

String.format(

"data {%s}, thread {%s}"

, LocalDateTime.now().format(formatter), Thread.currentThread().getName()); } } /<code>

控制檯輸出的結果:

美團面試真題之一個線程OOM,進程裡的其他線程還能運行嗎?

從日誌中可以看出,線程oom-thread線程溢出了,其他線程not-oom-thread線程還在執行中。使用jvisualvm監控下。

設置的jvm參數:

<code>

-Xmx32m

-Xms32m

-XX

:+UseConcMarkSweepGC

-XX

:+PrintGCDetails

-verbose

:gc

-XX

:+PrintGCDateStamps

-Xloggc

:E

:/

gc

.log

/<code>

1

分析gc日誌,可以看出老年代的內存使用率達到99.79%。內存使用率已經滿了。出現內存溢出。

美團面試真題之一個線程OOM,進程裡的其他線程還能運行嗎?

上面是jvisualvm監控堆內存變化的結果,注意看圖上,拋出OOM的時間在14:56:54左右,重點關注這個時間點左右的曲線變化。發現堆使用的數量突然間急速下滑,這代表這一點,當一個線程拋出OOM異常後,它說佔用的內存空間會全部被釋放掉,從而不會影響其他線程的運行。

這個例子只是演示了堆內存溢出的情況,如果是棧內存溢出,結論也是一樣的。


分享到:


相關文章: