線程的運行原理


一、棧與棧幀

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 頻繁發生會影響性能
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM