標籤: dem 開始 結束 pos tar 簡單 min 使用
本文目錄
1 線程與多線程
線程是什嗎?
線程(Thread)是一個對象(Object)。用來幹什嗎?Java 線程(也稱 JVM 線程)是 Java 進程內允許多個同時進行的任務。該進程內並發的任務成為線程(Thread),一個進程裡至少一個線程。
Java 程式採用多線程方式來支援大量的並發請求處理,程式如果在多線程方式執行下,其複雜度遠高於單線程串列執行。那麼多線程:指的是這個程式(一個進程)運行時產生了不止一個線程。
為啥使用多線程?
- 適合多核處理器。一個線程運行在一個處理器核心上,那麼多線程可以分配到多個處理器核心上,更好地利用多核處理器。
- 防止阻塞。將資料一致性不強的操作使用多線程技術(或者訊息佇列)加快代碼邏輯處理,縮短回應時間。
聊到多線程,多半會聊並發與並行,咋理解並區分這兩個的區別呢?
- 類似單個 CPU ,通過 CPU 調度演算法等,處理多個任務的能力,叫並發
- 類似多個 CPU ,同時並且處理相同多個任務的能力,叫做並行
2 線程的運行與建立2.1 線程的建立
Java 建立線程對象有兩種方法:
- 繼承 Thread 類建立線程對象
- 實現 Runnable 介面類建立線程對象
建立 MyThread 對象,代碼如下:
/** * 繼承 Thread 類建立線程對象 * @author Jeff Lee @ bysocket.com * @since 2018年01月27日21:03:02 */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 的線程對象 10MyThread 的線程對象正在執行任務MyThread 的線程對象 11MyThread 的線程對象正在執行任務MyThread 的線程對象 12MyThread 的線程對象正在執行任務MyThread 的線程對象 13MyThread 的線程對象正在執行任務MyThread 的線程對象 14MyThread 的線程對象正在執行任務MyThread 的線程對象 15MyThread 的線程對象正在執行任務MyThread 的線程對象 16MyThread 的線程對象正在執行任務MyThread 的線程對象 17MyThread 的線程對象正在執行任務MyThread 的線程對象 18MyThread 的線程對象正在執行任務MyThread 的線程對象 19
可見,線程的 ID 是線程唯一識別碼,每個線程 ID 都是不一樣的。
start 方法和 run 方法的關係:
同理,實現 Runnable 介面類建立線程對象也很簡單,只是不同的形式。建立 MyThreadBrother 代碼如下:
/** * 實現 Runnable 介面類建立線程對象 * @author Jeff Lee @ bysocket.com * @since 2018年01月27日21:22:57 */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()); } }}
具體代碼:「java-concurrency-core-learning」
https://github.com/JeffLi1993/java-concurrency-core-learning
2.1 線程的運行
在運行上面兩個小 demo 後,JVM 執行了 main 函數線程,然後在主線程中執行建立了新的線程。正常情況下,所有線程執行到運行結束為止。除非某個線程中調用了 System.exit(1) 則被終止。
在實際開發中,一個請求到響應式是一個線程。但在這個線程中可以使用線程池建立新的線程,去執行任務。
3 線程的狀態
建立 MyThreadInfo 類,列印線程對象屬性,代碼如下:
/** * 線程執行個體對象的屬性值 * @author Jeff Lee @ bysocket.com * @since 2018年01月27日21:24:40 */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 的線程對象 \n" + "線程唯一識別碼:" + thread.getId() + "\n" + "線程名稱:" + thread.getName() + "\n" + "線程狀態:" + thread.getState() + "\n" + "線程優先順序:" + 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(終止)。狀態轉換圖如下:
線程狀態流程大致如下:
- 線程建立後,進入 new 狀態
- 調用 start 或者 run 方法,進入 runnable 狀態
- JVM 按照線程優先順序及時間分區等執行 runnable 狀態的線程。開始執行時,進入 running 狀態
- 如果線程執行 sleep、wait、join,或者進入 IO 阻塞等。進入 wait 或者 blocked 狀態
- 線程執行完畢後,線程被線程隊列移除。最後為 terminated 狀態。
4 小結
本文介紹了線程與多線程的基礎篇,包括了線程啟動及線程狀態等。下一篇我們聊下線程的具體操作。包括中斷、終止等
具體代碼:「java-concurrency-core-learning」
https://github.com/JeffLi1993/java-concurrency-core-learning
參考:
《Java並發編程的藝術》
《Java 7 並發編程實戰手冊》
《圖解 Java 多線程設計模式》
泥瓦匠聊並發編程:線程與多線程必知必會(基礎篇)