Java - 内存分析:多线程调度

多线程调度内存分析:给定以下多线程实现相关代码,观察和分析不同线程在内存中的的调度过程

一、绘制内存结构图

Java - 内存分析:多线程调度

二、类加载

将 Thread 和 DemoThread 类的字节码文件加载到方法区中Java - 内存分析:多线程调度

三、启动 main 线程

程序总是从 main() 方法开始执行,首先,JVM在栈区中创建并启动一个 main 线程栈。然后在 main 线程栈中为 main 方法开辟一个栈帧,将 main() 方法压栈
Java - 内存分析:多线程调度

四、启动其它线程

  • MyThread mt1 = new MyThread():在 main 线程中的 main 方法创建变量 mt1 并压入main方法栈帧,同时在堆中实例化一个 MyThread 线程对象,将 MyThread 对象的地址赋值给 mt1
  • mt1.start():启动 mt1 指向的线程对象,在栈区中创建一个新的线程栈,为便于理解,令其名为 mt1 线程栈;然后在 mt1 线程栈中为该线程的 run() 方法开辟一段栈帧并压入 mt1 线程栈

Java - 内存分析:多线程调度
同理,实例化 mt2 线程对象并启动

Java - 内存分析:多线程调度

五、争夺 CPU 执行权

此时,栈区中有三个线程栈。观察线程类中对 run() 方法的定义以及 main() 方法中的剩余代码可知:三条线程的任务均为执行一个迭代 20 次的 for 循环,每轮循环中打印一些内容。Java - 内存分析:多线程调度
由于 Java 采用的是抢占式调度,再不设置线程优先级的前提下,CPU 每次将从三条线程中随机选择一条线程进行执行。直至所有线程全部执行完毕后,各个线程栈将内部的方法依次弹栈,GC将堆和方法区中的内容回收,程序执行结束。

在此笔者有一个小问题:如果 main 方法多次抢到了 CPU 的执行权,且最先完成了循环体的执行,那么 main 线程是直接将 main() 方法弹栈呢?还是等待 mt1 线程和 mt2 线程全部执行完毕弹栈后再将 main() 方法弹栈呢?有了解的大佬可以在评论区解答一下哈~