一、棧與棧幀
Java Virtual Machine Stacks (Java 虛擬機棧)
我們都知道 JVM 中由堆、棧、方法區所組成,其中棧內存是給誰用的呢?其實就是線程,每個線程啟動后,虛擬
機就會為其分配一塊棧內存。
每個棧由多個棧幀(Frame)組成,對應着每次方法調用時所占用的內存
每個線程只能有一個活動棧幀,對應着當前正在執行的那個方法
二、運行過程
public static void main(String[] args) { method1(10); } static void method1(int x) { int y = x + 1; Object m = method2(); System.out.printf(m.toString()); } static Object method2() { Object n = new Object(); return n; } }
1.將編譯好的字節碼加載到jvm的方法區內存中
2.jvm啟動一個main的主線程,cpu核心就准備運行主線程的代碼了,給主線程分配自己的棧內存【args、局部變量、返回地址、所記錄】,每個線程的棧里面還有個程序計數器
程序計數器的作用:當cpu要執行哪行代碼了,就去這個里面去要
3.把主方法的里面代碼行放到程序計數器
4.主方法調用的是method1的方法,為method1分配棧內存,里面存儲這個方法里面局部變量,返回地址,這些變量是分配內存時,會把空間預留好
5.將method1的第一行讀到程序計數器讓cpu執行
6.methode1下一行調用method2()方法,創建他的棧內存
7.把Object n = new Object()這行代碼讀取到計數器,在隊中創建對象
8.method2()將返回地址給m,方法執行完就可以釋放掉method2()的棧內存
9.一層層方法結束后,依次釋放掉每個方法線程

三、多線程執行邏輯
public class frameTest { public static void main(String[] args) { //線程t1 Thread t1 = new Thread(new Runnable() { @Override public void run() { method1(20); } }); t1.start(); //主線程 method1(10); } static void method1(int x) { int y = x + 1; Object m = method2(); System.out.printf(m.toString()); } static Object method2() { Object n = new Object(); return n; } }
對上面代碼進行斷點調試查看:
兩個線程的狀態:
三.線程上下文切換(Thread Context Switch)
因為以下一些原因導致 cpu 不再執行當前的線程,轉而執行另一個線程的代碼
1.線程的 cpu 時間片用完
2.垃圾回收
3.有更高優先級的線程需要運行
4.線程自己調用了 sleep、yield、wait、join、park、synchronized、lock 等方法
原理:
1.當 Context Switch 發生時,需要由操作系統保存當前線程的狀態,並恢復另一個線程的狀態,Java 中對應的概念
就是程序計數器(Program Counter Register),它的作用是記住下一條 jvm 指令的執行地址,是線程私有的
2.狀態包括程序計數器、虛擬機棧中每個棧幀的信息,如局部變量、操作數棧、返回地址等
3.Context Switch 頻繁發生會影響性能