网站首页 > 精选教程 正文
一个进程有3个线程,如果一个线程抛出OOM,其他两个线程还能运行吗?
答案是还能运行
不瞒大家说,正在面试中,我遇到这一题,我估计也会答错,因为我初看这一题的时候,觉得是在考察JVM的内存结构,我第一反应是OOM常见情况堆内存溢出,也就是下面的这种异常
java.lang.OutOfMemoryError:java heap space
多线程中栈与堆是公有还是私有的
在多线程环境下,每个线程拥有一个栈和一个程序计数器,栈和程序计数器用来保存线程执行历史和线程执行状态,是线程私有的,堆是由用一个进程内多个线程共享的。
测试代码伪代码如下:
一个线程去构造堆内存溢出,每隔ls申请一次堆内存。
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;
/**
* @className ThreadOOMTest
* @description 测试一个线程出现OOM,同进程下的其他线程还能继续运行吗?
* @author yangpengbing
* @date 22:12 2018/12/19
* @version 1.0.0
*/
@Slf4j
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();
}
/**
* 控制台输出时间和线程名称
* @param msg
*/
private static void show(String msg) {
System.out.println(msg);
}
/**
* 线程休眠1s
*/
private static void sleep() {
try {
TimeUnit.SECONDS.sleep(1L);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 格式化输出的信息
* @param formatter
* @return
*/
private static String format(DateTimeFormatter formatter) {
return String.format("data {%s}, thread {%s}", LocalDateTime.now().format(formatter), Thread.currentThread().getName());
}
}
控制台输出的结果:
从日志中可以看出,线程oom-thread线程溢出了,其他线程not-oom-thread线程还在执行中。使用jvisualvm监控下。
设置的jvm参数:
-Xmx32m -Xms32m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -verbose:gc -XX:+PrintGCDateStamps -Xloggc:E:/gc.log
1
分析gc日志,可以看出老年代的内存使用率达到99.79%。内存使用率已经满了。出现内存溢出。
上面是jvisualvm监控堆内存变化的结果,注意看图上,抛出OOM的时间在14:56:54左右,重点关注这个时间点左右的曲线变化。发现堆使用的数量突然间急速下滑,这代表这一点,当一个线程抛出OOM异常后,它说占用的内存空间会全部被释放掉,从而不会影响其他线程的运行。
这个例子只是演示了堆内存溢出的情况,如果是栈内存溢出,结论也是一样的。
- 上一篇: Java多线程-线程中断interrupt
- 下一篇: Java 17 多线程中的守护线程
猜你喜欢
- 2024-11-23 线程生命周期
- 2024-11-23 线程同步synchronized(不同步的问题、队列与锁),死锁产生和解决
- 2024-11-23 面试突击31:什么是守护线程?它和用户线程有什么区别?
- 2024-11-23 Java之TimeUnit的使用
- 2024-11-23 每日分享- NodeJS 程序中实现线程睡眠
- 2024-11-23 Java 17 多线程中的守护线程
- 2024-11-23 Java多线程-线程中断interrupt
- 2024-11-23 C++ 让线程休眠特定时间
- 2024-11-23 什么是线程死锁?形成条件是什么?如何避免?
- 2024-11-23 你能说出多线程中sleep、yield、join的用法及sleep与wait区别吗
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)