Java 工作线程OOM,会怎么样?
初看到这一问题,觉得这题是在考察JVM的内存结构。我第一反应是OOM的常见情况堆溢出,也就是下面的这种异常
java.lang.OutOfMemoryError: Java heap space
默想如下
在多线程环境下,每个线程拥有一个栈和一个程序计数器。栈和程序计数器用来保存线程的执行历史和线程的执行状态,是线程私有的资源。其他的资源(比如堆、地址空间、全局变量)是由同一个进程内的多个线程共享。
所以按照这个思路去思考的话,看到这个题目首先就会想到 如果堆内存是共享的话,那么单独的子线程内存溢出也就是堆占用满了 其他线程自然也就不能工作了。然后实验结果却不是这样
开始实验
编译工具:IDEA
电脑系统: Mac
内存检测工具:VisualVm
基本参数设置如下:
-mx80 -XX:MaxPermSize=50m
最大可用的堆内存是80M 最大可使用的非堆内存是50m按需分配
测试代码如下
public static void main(String[] args) {
long memory = Runtime.getRuntime().maxMemory();
System.out.println(String.format("%d (%.2f M)", memory, (double) memory / (1024 * 1024)));
Thread mThreadTest = new Thread(() -> {
List<byte[]> list = new ArrayList<byte[]>();
while (true) {
System.out.println(new Date().toString() + Thread.currentThread() + "==");
byte[] b = new byte[1024 * 10240 * 1];
list.add(b);
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
});
mThreadTest.start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("test");
}
}
}).start();
}
}
代码应该比较容易看懂,开了两个工作线程一个,第一个线程每隔3秒分配1m的内存空间,第二个每隔一秒输出一个test
注意看9:43:00 前后,内存到达一个峰值以后立刻就降下来了。并且打印出OutOfMemoryError,打印test的线程仍在继续运行
结论
当一个线程抛出OOM异常后,它所占据的内存资源会全部被释放掉,从而不会影响其他线程的运行!