这题是一个网友@大脸猫爱吃鱼给我的提问,出自今年校招美团三面的一个真题。大致如下:

一个进程有3个线程,如果一个线程抛出oom,其他两个线程还能运行么?

先说一下答案,答案是还能运行

不瞒大家说,真在面试中,我遇到这一题,我估计也是答错。因为我初看到这一题,内心嘿嘿一笑,觉得这题是在考察JVM的内存结构。我第一反应是OOM的常见情况堆溢出,也就是下面的这种异常:

java.lang.OutOfMemoryError: Java heap space

先回忆一下,多线程中栈与堆是公有的还是私有的?回答如下:

在多线程环境下,每个线程拥有一个栈和一个程序计数器。栈和程序计数器用来保存线程的执行历史和线程的执行状态,是线程私有的资源。其他的资源(比如堆、地址空间、全局变量)是由同一个进程内的多个线程共享。

也就是说,堆是线程共享。那么一个线程堆抛出OOM异常,我第一反应是另外两个线程也抛出OOM异常,毕竟堆是共有的,大家应该都抛出异常。于是,我机智的让@大脸猫爱吃鱼写个代码去测试一下,结果我被啪啪啪打脸了。


测试代码伪如下:

一个线程去构造堆溢出,每隔1S申请一次堆,代码长下面这样:

new Thread(() -> {List<byte[]> list=new ArrayList<byte[]>();while(true){System.out.println(new Date().toString()+Thread.currentThread()+"==");byte[] b = new byte[1024*1024*1];list.add(b);try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}}
}).start();

另一个线程,睡眠1秒然后输出就好,代码长下面这样:

new Thread(() -> {while(true){System.out.println(new Date().toString()+Thread.currentThread()+"==");try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}}
}).start();

结果,输出是长下面这样的:

Fri Sep 21 11:18:39 CST 2018Thread[Thread-1,5,main]==
Fri Sep 21 11:18:39 CST 2018Thread[Thread-0,5,main]==
Fri Sep 21 11:18:40 CST 2018Thread[Thread-1,5,main]==
Fri Sep 21 11:18:40 CST 2018Thread[Thread-0,5,main]==
Fri Sep 21 11:18:41 CST 2018Thread[Thread-1,5,main]==
Fri Sep 21 11:18:41 CST 2018Thread[Thread-0,5,main]==
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap spaceat com.lpf.TestOOM.lambda$0(TestOOM.java:15)at com.lpf.TestOOM$$Lambda$1/531885035.run(Unknown Source)at java.lang.Thread.run(Thread.java:748)
Fri Sep 21 11:18:42 CST 2018Thread[Thread-1,5,main]==
Fri Sep 21 11:18:43 CST 2018Thread[Thread-1,5,main]==
Fri Sep 21 11:18:44 CST 2018Thread[Thread-1,5,main]==
Fri Sep 21 11:18:45 CST 2018Thread[Thread-1,5,main]==
Fri Sep 21 11:18:46 CST 2018Thread[Thread-1,5,main]==

大家发现了么,一个线程溢出了,其他线程还在跑,这好像和我们的认知不大一样。坦白说,我看到这个结果,瞬间觉得自己一世英名毁于一旦,从此无法抬起头来做人。没办法了,只能亮出工具来看一下了。
先说一下,在本例测试中,参数如下:

-Xms16m -Xmx32m
-Xms 初始堆内存
-Xmx 最大堆内存

接下来,亮出JvisualVM看堆的变化,注意看上面那张图,抛出OOM的时间约在00:11:45左右,因此我们需要重点关注00:11:45左右的曲线变化,如下图所示:

如图所示,我们仔细观察一下在14:06:20~14:06:21之间曲线变化,你会发现使用堆的数量,突然间急剧下滑!这代表这一点,当一个线程抛出OOM异常后,它所占据的内存资源会全部被释放掉,从而不会影响其他线程的运行!

讲到这里大家应该懂了,此题的答案为一个线程溢出后,进程里的其他线程还能照常运行。注意了,这个例子我只演示了堆溢出的情况。如果是栈溢出,结论也是一样的,大家可自行通过代码测试。


完整代码

import java.util.ArrayList;
import java.util.Date;
import java.util.List;public class TestOOM {public static void main(String[] args) {// 线程一new Thread(() -> {List<byte[]> list = new ArrayList<byte[]>();while (true) {System.out.println(new Date().toString() + Thread.currentThread() + "==");byte[] b = new byte[1024 * 1024 * 1];list.add(b);try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}}}).start();// 线程二new Thread(() -> {while (true) {System.out.println(new Date().toString() + Thread.currentThread() + "==");try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}}}).start();}
}

运行时设置内存参数

面试系列 | 一个线程OOM,进程里其他线程还能运行么?相关推荐

  1. .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调、APM、EAP、TPL、aysnc、await

    windows系统是一个多线程的操作系统.一个程序至少有一个进程,一个进程至少有一个线程.进程是线程的容器,一个C#客户端程序开始于一个单独的线程,CLR(公共语言运行库)为该进程创建了一个线程,该线 ...

  2. 在VB中如何让线程或进程在指定的CPU上运行

    代码如下: Option Explicit Private Declare Function WTSEnumerateProcesses Lib "wtsapi32.dll" Al ...

  3. 面试官:一个线程OOM,进程里其他线程还能运行么?

    作者:孤独烟,资深后端工程师,业内知名原创作者! 引言 这题是一个网友@大脸猫爱吃鱼给我的提问,出自今年校招美团三面的一个真题.大致如下 一个进程有3个线程,如果一个线程抛出oom,其他两个线程还能运 ...

  4. java进程内存一直没释放_面试官:一个线程OOM,进程里其他线程还能运行么?...

    引言 这题是一个网友@大脸猫爱吃鱼给我的提问,出自今年校招美团三面的一个真题.大致如下 一个进程有3个线程,如果一个线程抛出oom,其他两个线程还能运行么? 先说一下答案,答案是还能运行 不瞒大家说, ...

  5. java基础巩固-宇宙第一AiYWM:为了维持生计,多高(多线程与高并发)_Part1~整起(线程与进程篇:线程概念、线程状态、线程死锁)

    这个题目我感觉很多大哥大姐和我一样,虽然夹在众位大哥大姐中跟着一块喊着"多线程与高并发"的口号,但是这里面其实包含的东西并不像名字里面这么少.现在就开始咱们的旅程吧. 特此感谢,低 ...

  6. python中线程和进程_python中线程和进程的简单了解

    一.操作系统.应用程序 1.硬件:硬盘.cpu.主板.显卡........ 2.装系统(本身也是一个软件): 系统就是一个由程序员写出来的软件,该软件用于控制计算机得硬盘,让他们之间进行互相配合. 3 ...

  7. java中的线程和进程,Java | 线程和进程,创建线程

    一.线程与进程 线程定义 进程中执行的一个代码段,来完成不同的任务 组成:线程ID,当前指令指针(PC),寄存器集合(存储一部分正在执行线程的处理器状态的值)和堆栈 进程定义 执行的一段程序,一旦程序 ...

  8. 线程和进程的区别 线程和进程有什么不同

    进程是资源分配的最小单位,线程是资源调度的最小单位. 线程是在进程下运行的.一个进程可以包含多个线程. 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间.而线程是共享进程中的数据的, ...

  9. 【多线程】线程与进程、以及线程进程的调度

    在了解多线程之前,首先要区分线程和进程的概念与区别,我目前只了解到Java的JVM中与操作系统联系中的线程和进程,在了解线程与进程之前,首先要初步了解电脑中的操作系统的地位和作用. 冯诺依曼体系 计算 ...

  10. 0820Python总结-线程队列,进程池和线程池,回调函数,协程

    一.线程队列 from queue import Queue put 存 get 取 put_nowait 存,超出了队列长度,报错 get_nowait 取,没数据时,直接报错 Linux Wind ...

最新文章

  1. 云计算还是python_云计算 与python
  2. 图纸管理软件_图纸文件管理操作繁琐?巧用“权限”,管理更高效
  3. jmeter实现翻页功能_JMeter定制功能实现
  4. 信息学奥赛C++语言:分糖果
  5. [转]分布式中Redis实现Session终结篇
  6. plc与python之间实现通信的结构框图_Python设计模式 - UML - 通信图(Communication Diagram)...
  7. 输出毫秒_使用AMETEK直流电源实现波形变化的输出
  8. jq输出html 单引号引号转义符,javascript - 由于JSON中的单引号转义,jQuery.parseJSON抛出“无效的JSON”错误...
  9. 从贝叶斯模型(Bayes)到生成模型(Generative models)(生成式分类器,generative classifier)
  10. UVA12897 - Decoding Baby Boos
  11. PHP 命令行之-F (--process-file) 对每个输入行都执行 PHP 文件 (PHP 5 新加)
  12. 原版windows下载地址
  13. ubuntu安装atat
  14. 微信二维码无法下载APK解决方案
  15. 华为确定发布鸿蒙的时间了吗,Mate40系列首发,华为鸿蒙OS手机版发布时间确定...
  16. 莫斯卡托葡萄酒的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  17. history对象back()、forward()、go()方法
  18. Android BitmapFactory.decodeResource()方法参数代表什么意思
  19. 计算机用户使用品牌调查报告,品牌电脑市场调查报告
  20. 疫后如何激活消费?上海和阿里打了个样板

热门文章

  1. 汽车加油站问题(Java)
  2. 定制Hexo-NexT的个性化博客
  3. postgresql数据库 timescaledb 时序库 超级表 块的压缩(compress_chunk()的应用)
  4. 厦门大学计算机系录取分数线贵州,厦门大学2016年在贵州各专业录取分数线
  5. 游侠更新仙剑全系列免CD补丁(支持WIN7 SP1)【转载】
  6. 群同态和群同构的区别_抽象代数3-1群同态的简单性质与低阶群的结构
  7. html直线动画,HTML5 Canvas流动线条动画特效
  8. oracle删除目录 数据库文件,数据库生成一个app文件夹为什么删不掉
  9. 【CZY选讲·逆序对】
  10. 通过cmd查询自己电脑的操作系统是32位还是64位