一、JVM 中的线程
我们都知道 JVM 是由堆、栈、方法区所组成,其中栈内存是给谁用的呢?其实就是线程,每个线程启动后,虚拟机就会为其分配一块栈内存。
- 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存
- 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法。
下面先看一段只有主线程的代码,分析内存图:
/**
* 测试栈帧
* @author 落霞不孤
*/
public class TestFrames {
public static void main(String[] args) {
// Thread t1 = new Thread(() -> {method1(20);}, "t1");
// t1.start();
method1(10);
}
private static void method1(int x) {
int y = x + 1;
Object m = method2();
System.out.println(m);
}
private static Object method2() {
Object n = new Object();
return n;
}
}
运行这段代码,JVM 首先开启一个 main 的线程栈空间,里面由程序计数器(记录程序执行的行数)和栈帧(每调用一个方法就生成一个栈帧)构成。其中栈帧内部由局部变量表、锁记录、返回地址、操作数栈等等,我们中间 new 的对象在堆上面,这个过程如下图所示:
如果由 main 方法中多个线程,那么内存分布图变为下图:
和只有一个线程的图差不多,每个线程都维护了一个程序计数器,因此当发生线程上下文切换的时候 CPU 就可以知道每个线程执行到哪一步。
二、IDEA 中调试多线程的程序
-
在线程定义位置打下断点,断点处右键选择 Thread 模式
-
启动 Debug 模式,调试的步骤和普通的程序调试一样,在 DeBug 窗口,我们可以观察到有两个线程在运行
-
当
main线程执行完毕,我们可以切换到t1线程,可以发现,它并没有随着主线程的结束而结束
- 当两个线程都结束以后,整个程序才是真正地结束了。