线程运行原理
栈与栈帧 Java Virtual Machine Stacks (Java 虚拟机栈)
我们都知道 JVM 中由堆、栈、方法区所组成,其中栈内存是给谁用的呢?其实就是线程,每个线程启动后,虚拟机就会为其分配一块栈内存。 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存,每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法。
代码解释
我们对这样一段代码进行调试:(先在main方法中的method1(10);处打上断点)
@Slf4j
public class Test3_4 {
public static void main(String[] args) {
method1(10);
}
public static void method1(int x){
int y = x + 1;
Object m = method2();
System.out.println(m);
}
public static Object method2(){
Object n = new Object();
return n;
}
}
1.我们可以看到在栈中创建了“main”栈帧:
2.点击步入,然后我们可以看到在栈中多了method1的栈帧,并且给x赋了值“10”。
3.连续步入两次,就会发现创建了method2帧:
4.继续步入,发现在method2执行玩return n后 method2的栈帧消失了:
5.method1也是一样
代码对应图解:
1.cpu核心分配给了main线程栈,创建了main栈帧。
2.程序计数器读到了method1方法,于是创建了method1栈帧,添加了x,y,m局部变量,并且,让x=10,记录了返回地址。
3,方法计数器读到method2方法,创建了method2栈帧。
4,在return n执行完毕后,删除了method2的栈帧,(堆中的 new Object()是method2创建的)
5,
线程上下文切换(Thread Context Switch)
因为以下一些原因导致 cpu 不再执行当前的线程,转而执行另一个线程的代码
1,线程的 cpu 时间片用完
2,垃圾回收
3,有更高优先级的线程需要运行
4,线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法
当 Context Switch 发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,Java 中对应的概念 就是程序计数器(Program Counter Register),它的作用是记住下一条 jvm 指令的执行地址,是线程私有的。
1,状态包括程序计数器、虚拟机栈中每个栈帧的信息,如局部变量、操作数栈、返回地址等
2,Context Switch 频繁发生会影响性能