线程之间互相不影响;守护线程生活周期相同

引言

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

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

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

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

java.lang.OutOfMemoryError: Java heap space

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

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

也就是说,堆是线程共享。那么一个线程堆抛出OOM异常,我第一反应是另外两个线程也抛出OOM异常,毕竟堆是共有的,大家应该都抛出异常。于是,我机智的让@大脸猫爱吃鱼写个代码去测试一下,结果我被啪啪啪打脸了。
测试代码伪如下
一个线程去构造堆溢出,每隔1秒申请一次堆,代码长下面这样

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();

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

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

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

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

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

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

说时迟,那时快。一个机智的网友又给我提了一个问题?

如果主线程抛异常退出了,子线程还能运行么?

ok,这个问题要从子线程和主线程的关系讲起。
先来一个定义

线程不像进程,一个进程中的线程之间是没有父子之分的,都是平级关系。即线程都是一样的, 退出了一个不会影响另外一个。

因此,答案是如果主线程抛异常退出了,子线程还能运行。
但是有一个例外情况,如果这些子线程都是守护线程,那么子线程会随着主线程结束而结束。

作者:孤独烟
出处:http://rjzheng.cnblogs.com/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】

一个线程oom,进程里其他线程还能运行吗?的更多相关文章

  1. 【原创】一个线程oom,进程里其他线程还能运行吗?

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

  2. 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型

    一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...

  3. Python 开启线程的2中方式,线程VS进程(守护线程、互斥锁)

    知识点一: 进程:资源单位 线程:才是CPU的执行单位 进程的运行: 开一个进程就意味着开一个内存空间,存数据用,产生的数据往里面丢 线程的运行: 代码的运行过程就相当于运行了一个线程 辅助理解:一座 ...

  4. 12 并发编程-(线程)-线程queue&进程池与线程池

    queue 英 /kjuː/ 美 /kju/ 队列 1.class queue.Queue(maxsize=0) #队列:先进先出 import queue q=queue.Queue() q.put ...

  5. day35:线程队列&进程池和线程池&回调函数&协程

    目录 1.线程队列 2.进程池和线程池 3.回调函数 4.协程:线程的具体实现 5.利用协程爬取数据 线程队列 1.线程队列的基本方法 put 存 get 取 put_nowait 存,超出了队列长度 ...

  6. GIL全局解释器锁+GIL全局解释器锁vs互斥锁+定时器+线程queue+进程池与线程池(同步与异步)

    以多线程为例写个互斥锁 from threading import Thread ,Lockimport timemutex = Lock() n = 100 def task(): global n ...

  7. 计算机必知必会:进程process与线程thread 进程定义为一个正在运行的程序的实例

    http://www.nowamagic.net/librarys/veda/detail/1741进程和线程这对概念的理解也是很难的,至今网络上可查的资料对其的理解出入都挺大,在不同的操作系统中,如 ...

  8. paramiko模块,线程,进程

    关于paramiko模块 paramiko是基于Python实现的ssh2远程安全连接,支持认证及密钥方式远程执行命令.文件传输,中间ssh代理等 paramiko的安装: 安装好之后,用parami ...

  9. Linux 线程与进程,以及通信

    http://blog.chinaunix.net/uid-25324849-id-3110075.html 部分转自:http://blog.chinaunix.net/uid-20620288-i ...

随机推荐

  1. spark 笔记 6: RDD

    了解RDD之前,必读UCB的论文,个人认为这是最好的资料,没有之一. http://www.cs.berkeley.edu/~matei/papers/2012/nsdi_spark.pdf A Re ...

  2. centos6 yum安装mysql 5.6 (完整版)

    使用源代码编译安装mysql还是比较麻烦,一般来说设备安装时请网络同事临时开通linux上网,通过yum网络实现快速安装,或配置yum仓库进行内网统一安装. 通过网络快速安装过程如下 一.检查系统是否 ...

  3. 评【TED】陆克文:中美注定要冲突吗?

    陆克文TED演讲地址:https://www.bilibili.com/video/av2196100?from=search&seid=6953438337852168205 实话说,这篇材 ...

  4. Dark 类与对象

    1 类的声明 使用class声明一个类 使用new 创建一个对象,new可省略 dark文件名和声明的类名可以不一样,与java不同 void main() { var function = Pers ...

  5. swiper 的左右箭头放到轮播外面

    <!-- 增加一个father的包裹 --> <div class="swiper-father"> <div class="swiper- ...

  6. java 接口default的判断规则

    1.前言 jdk1.8中新增加了default关键字,就是在接口中可以增加默认实现. 因为改动接口所有的实现类都要改动,所以增加了default关键字后不需要修改其他类,默认给所有实现类增加了方法. ...

  7. cf1151e number of components

    很常见的思想:将整体求改为统计每个部分的贡献 本题中统计[l, r]时, 每个连通块有一个重要特征, 最右端的数在[l,r]中而下一个数不在(好像是句废话 那么我们分别考虑每个点对连通块的贡献, 即它 ...

  8. 平衡树(fhq无旋treap)

    fhq板子(代码正确且风格易懂) 洛谷P3369 #include<iostream> #include<cstring> #include<cstdio> #in ...

  9. 微信小程序 解析html格式内容

    需要引入html-view文件 1/js 代码 const HtmlParser=require('../../utils/html-view/index') data: { coupon_text: ...

  10. python 迭代器(第二次总结)

    迭代器 1.先明白迭代器是什么意思 迭代:不断的取值的(器)工具 迭代器:就是一个重复的过程,每一次重复都是基于上一次的结果而来的. (单纯的重复不是迭代) 2.为什么要有迭代器 不依赖索引取值的方法 ...