Java併發(四)----線程運行原理

1、線程運行原理

1.1 棧與棧幀  

Java Virtual Machine Stacks (Java 虛擬機棧 JVM)

我們都知道 JVM 中由堆、棧、方法區所組成,其中棧內存是給誰用的呢?其實就是線程,每個線程啓動後,虛擬機就會爲其分配一塊棧內存。

  • 每個棧由多個棧幀(Frame)組成,對應着每次方法調用時所佔用的內存

  • 每個線程只能有一個活動棧幀,對應着當前正在執行的那個方法

單線程示例代碼

public class TestFrames {
    public static void main(String[] args) {
        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;
    }
}

在打斷點處,可以看到一個棧幀

執行到method1,可以看到新起了一個棧幀

當執行到method2時,可以看到又新起了一個棧幀

由於是棧,隨着的程序的運行,後面開啓的棧幀會先被銷燬,直至main棧幀被銷燬,此刻程序運行完成。

對應圖解:

內存釋放後

具體就是:

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 TestFrames {
    public static void main(String[] args) {
        Thread t1 = new Thread(){
            @Override
            public void run() {
                method1(20);// 斷點處
            }
        };
        t1.setName("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;
    }
}
​

在第一個斷點處

可以看到多個線程同時運行中,我們可以選擇具體的線程來查看運行狀況並且往下運行,具體的讀者可以自行實踐。

1.2 線程上下文切換(Thread Context Switch)

因爲以下一些原因導致 cpu 不再執行當前的線程,轉而執行另一個線程的代碼(簡單來說就是從使用cpu到不使用cpu

  • 線程的 cpu 時間片用完

  • 垃圾回收

  • 有更高優先級的線程需要運行

  • 線程自己調用了 sleep、yield、wait、join、park、synchronized、lock 等方法

當 Context Switch(上下文切換) 發生時,需要由操作系統保存當前線程的狀態,並恢復另一個線程的狀態,Java 中對應的概念就是程序計數器(Program Counter Register),它的作用是記住下一條 jvm 指令的執行地址,是線程私有的

  • 狀態包括程序計數器、虛擬機棧中每個棧幀的信息,如局部變量、操作數棧、返回地址等

  • Context Switch 頻繁發生會影響性能,因爲線程數不是越多越好。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章