Java線程與多線程 原

1 線程與多線程

1.1 線程是什麼?

線程(Thread)是一個對象(Object)。用來幹什麼?Java 線程(也稱 JVM 線程)是 Java 進程內允許多個同時進行的任務。該進程內併發的任務成爲線程(Thread),一個進程裏至少一個線程。

Java 程序採用多線程方式來支持大量的併發請求處理,程序如果在多線程方式執行下,其複雜度遠高於單線程串行執行。那麼多線程:指的是這個程序(一個進程)運行時產生了不止一個線程。

1.2 爲啥使用多線程?

  • 適合多核處理器。一個線程運行在一個處理器核心上,那麼多線程可以分配到多個處理器核心上,更好地利用多核處理器。
  • 防止阻塞。將數據一致性不強的操作使用多線程技術(或者消息隊列)加快代碼邏輯處理,縮短響應時間。

聊到多線程,多半會聊併發與並行,咋理解並區分這兩個的區別呢?

  • 類似單個 CPU ,通過 CPU 調度算法等,處理多個任務的能力,叫併發
  • 類似多個 CPU ,同時並且處理相同多個任務的能力,叫做並行

2 線程的創建與運行

2.1 線程的創建

Java 創建線程對象有兩種方法:

  • 繼承 Thread 類創建線程對象
  • 實現 Runnable 接口類創建線程對象

2.1.1 繼承 Thread 類創建線程對象

新建 MyThread 對象,代碼如下:

public class MyThread extends Thread { 
    @Override // 可以省略 
    public void run() { 
        System.out.println("MyThread 的線程對象正在執行任務"); 
    } 
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            MyThread thread = new MyThread();
            thread.start();
            System.out.println("MyThread 的線程對象 " + thread.getId()); 
        } 
    }
}

MyThread 類繼承了 Thread 對象,並重寫(Override)了 run 方法,實現線程裏面的邏輯。main 函數是使用 for 語句,循環創建了 10 個線程,調用 start 方法啓動線程,最後打印當前線程對象的 ID。

** run 方法和 start 方法的區別是什麼呢?**

  • run 方法就是跑的意思,線程啓動後,會調用 run 方法。

  • start 方法就是啓動的意思,就是啓動新線程實例。啓動線程後,纔會調線程的 run 方法。

執行 main 方法後,控制檯打印如下:

MyThread 的線程對象正在執行任務
MyThread 的線程對象 10
MyThread 的線程對象正在執行任務
MyThread 的線程對象 11
MyThread 的線程對象正在執行任務
MyThread 的線程對象 12
MyThread 的線程對象正在執行任務
MyThread 的線程對象 13
MyThread 的線程對象正在執行任務
MyThread 的線程對象 14
MyThread 的線程對象正在執行任務
MyThread 的線程對象 15
MyThread 的線程對象正在執行任務
MyThread 的線程對象 16
MyThread 的線程對象正在執行任務
MyThread 的線程對象 17
MyThread 的線程對象正在執行任務
MyThread 的線程對象 18
MyThread的線程對象正在執行任務
MyThread 的線程對象 19

可見,線程的 ID 是線程唯一標識符,每個線程 ID 都是不一樣的。

start 方法和 run 方法的關係如圖所示:

image

2.1.2 實現 Runnable 接口類創建線程對象

實現 Runnable接口類創建線程對象也很簡單,只是不同的形式。

新建 MyThreadBrother 代碼如下:

public class MyThreadBrother implements Runnable { 
    @Override // 可以省略 
    public void run() { 
        System.out.println("MyThreadBrother 的線程對象正在執行任務"); 
    } 
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new MyThreadBrother()); thread.start(); System.out.println("MyThreadBrother 的線程對象 " + thread.getId()); 
        } 
    }
}

2.2 線程的運行

在運行上面兩個小 demo 後,JVM 執行了 main函數線程,然後在主線程中執行創建了新的線程。正常情況下,所有線程執行到運行結束爲止。除非某個線程中調用了 System.exit(1) 則被終止。

在實際開發中,一個請求到響應式是一個線程。但在這個線程中可以使用線程池創建新的線程,去執行任務。

image

3 線程的狀態

新建 MyThreadInfo 類,打印線程對象屬性,代碼如下:

public class MyThreadInfo extends Thread {
    @Override // 可以省略 
    public void run() { 
        System.out.println("MyThreadInfo 的線程實例正在執行任務");
        // System.exit(1); 
    } 
    public static void main(String[] args) {
        MyThreadInfo thread = new MyThreadInfo(); 
        thread.start();
        System.out.print("MyThreadInfo 的線程對象 " + "線程唯一標識符:" + thread.getId() + " " + "線程名稱:" + thread.getName() + " " + "線程狀態:" + thread.getState() + " " + "線程優先級:" + thread.getPriority()); 
    }
}

執行代碼打印如下:

MyThreadInfo 的線程實例正在執行任務
MyThreadInfo 的線程對象 線程唯一標識符:10 線程名稱:Thread-0 線程狀態:NEW 線程優先級:5

線程是一個對象,它有唯一標識符 ID、名稱、狀態、優先級等屬性。線程只能修改其優先級和名稱等屬性 ,無法修改 ID 、狀態。ID 是 JVM 分配的,名字默認也爲 Thread-XX,XX是一組數字。線程初始狀態爲 NEW。

線程優先級的範圍是 1 到 10 ,其中 1 是最低優先級,10 是最高優先級。不推薦改變線程的優先級,如果業務需要,自然可以修改線程優先級到最高,或者最低。

線程的狀態實現通過 Thread.State 常量類實現,有 6 種線程狀態:new(新建)、runnnable(可運行)、blocked(阻塞)、waiting(等待)、time waiting (定時等待)和 terminated(終止)。狀態轉換圖如下: image

線程狀態流程大致如下:

  • 線程創建後,進入 new 狀態
  • 調用 start 或者 run 方法,進入 runnable 狀態
  • JVM 按照線程優先級及時間分片等執行 runnable 狀態的線程。開始執行時,進入 running 狀態
  • 如果線程執行 sleep、wait、join,或者進入 IO 阻塞等。進入 wait 或者 blocked 狀態
  • 線程執行完畢後,線程被線程隊列移除。最後爲 terminated 狀態。

如果本文有幫助到你,希望能動動小手點個贊。 如有錯誤請多指正!如有雷同!純屬巧合!

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