JavaSE 線程(上)
一、基本概念: 程序 - 進程 - 線程
-
**程序(program)**是爲完成特定任務、用某種語言編寫的一組指令的集合。就是一段代碼,靜態對象。
-
**進程(process)**是程序的一次執行過程,或是正在運行的一個程序。動態過程:有自身的產生、存在和消亡的過程。
- 比如:QQ,網易雲音樂。
- 程序是靜態的,進程是動態的。
-
**線程(thread)**是進程的細化,是一個程序內部的一條執行路徑。
- 如果一個程序可以同時執行多個線程,就是支持多線程的。
可以這麼認爲:程序就是靜止的代碼,進程就是運行着的代碼,線程就是運行時代碼的支流。
何時使用多線程
-
程序需要同時執行兩個/多個任務。
-
程序需要實現一些需要等待的任務時,如用戶輸入、文件讀寫操作、網絡操作、搜索等。
-
需要一些後臺運行的程序時。
二、多線程的創建和啓動
Java語言的JVM允許程序運行多個線程,它通過java.lang.Thread類來實現。
Thread類的特性
- 每個線程都是通過某個特定Thread對象的run()方法來完成操作,經常把run()方法的主體成爲線程體。
- 通過Thread對象的start()方法來啓動這個線程,本質上是運行run()方法。
1 繼承Thread類實現多線程
-
創建步驟
- 定義子類繼承Thread類
- 子類中重寫Thread類中的run方法
- 創建Thread子類對象,即創建了線程對象
- 調用線程對象start方法:啓動線程,調用run方法
-
案例展示:
package com.thread; /** * 繼承Thread類的方式實現多線程 */ public class TestThread extends Thread{ @Override public void run() { System.out.println("多線程運行的代碼"); for (int i = 0; i < 5; i++) { System.out.println("這是多線程的邏輯代碼" + i); } } }
package com.thread; public class Test { public static void main(String[] args) { Thread t0 = new TestThread(); t0.start(); //啓動線程 System.out.println("----------------"); System.out.println("----------------"); System.out.println("----------------"); } } /*運行結果: 多線程運行的代碼 ---------------- ---------------- 這是多線程的邏輯代碼0 這是多線程的邏輯代碼1 這是多線程的邏輯代碼2 這是多線程的邏輯代碼3 這是多線程的邏輯代碼4 ---------------- */
-
運行結果說明:
多次運行main方法後發現,打印結果中3行分隔符與開啓線程運行run()方法中打印語句是混合起來的且打印語句順序不固定!Why?
- 因爲main執行t0.start()開啓多線程之後,就相當於在main方法之外開啓了一個支流。
- 而這個支流代碼的執行和main方法之後代碼的執行就可認爲是同時運行。
- 那麼控制檯輸出的結果就是兩條並行程序的運行結果總和,這個結果就需要拆開成兩部分來看,總體上順序是混亂的,但是各自來看保持自己輸出順序。
這就體現了類多線程的異步性(相對於主程序來說)
2 實現Runnable接口實現多線程
-
創建步驟
-
定義子類,實現Runnable接口
-
子類中重寫接口中的run方法
-
通過Thread類含參構造器創建線程對象
-
將Runnable接口中的子類對象作爲實際參數傳遞給Thread類的構造方法中
通俗點:3、4就是
Thread t = new Thread(new TestRunnable()); //也可加入線程名稱
-
調用Thread類的start方法:開啓線程,調用run方法
-
-
案例展示:
package com.thread; /** * 通過實現Runnable接口方式實現多線程 */ public class TestRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"Runnable多線程運行的代碼"); for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+"這是Runnable多線程的邏輯代碼" + i); } } }
package com.thread; public class Test2 { public static void main(String[] args) { Thread t0 = new Thread(new TestRunnable()); t0.start(); Thread t1 = new Thread(new TestRunnable(),"t-1");//可傳入線程名稱 t1.start(); System.out.println("----------------"); System.out.println("----------------"); System.out.println("----------------"); } } /*運行結果: t-1Runnable多線程運行的代碼 t-1這是Runnable多線程的邏輯代碼0 t-1這是Runnable多線程的邏輯代碼1 t-1這是Runnable多線程的邏輯代碼2 t-1這是Runnable多線程的邏輯代碼3 t-1這是Runnable多線程的邏輯代碼4 Thread-0Runnable多線程運行的代碼 Thread-0這是Runnable多線程的邏輯代碼0 Thread-0這是Runnable多線程的邏輯代碼1 Thread-0這是Runnable多線程的邏輯代碼2 Thread-0這是Runnable多線程的邏輯代碼3 Thread-0這是Runnable多線程的邏輯代碼4 ---------------- ---------------- ---------------- */
對運行結果的說明可查看上個案例的說明,均體現了多線程的異步性。
3 兩種繼承方式和實現方式的聯繫和區別
【區別】
- 繼承Thread:線程代碼存放在Thread的子類的run方法中。(重寫)
- 實現Runnable:線程代碼存放在接口的子類的run方法中。(實現)
【實現Runnable方式的好處】
- 避免了單繼承的侷限性。(因爲接口可以實現間接實現多繼承)
- 多個線程可以共享同一個接口實現類的對象,非常適合多個相同線程共享同一份資源。(使用同一個實現了Runnable接口的類實例即可共享資源)
因此一般使用實現接口的方式來實現多線程!!!
使用多線程的優點
- 提高應用程序的響應。對圖形化界面更有意義,可增強用戶體驗。
- 提高計算機系統CPU的利用率。
- 改善程序結構。將既長又複雜的進程分爲多個線程,獨立運行,利於理解和修改。
例如: 如果有一個方法裏有1000行代碼,前300,中間300,最後400行這三段代碼,沒有因果關係,這種情況就可以使用線程處理,把前中後三段代碼分別放在不同的線程中去運行,這樣三段代碼就是並行運行的。效率更高!
寫在最後
謙卑是看別人比自己好,自卑是看別人比自己差,兩者截然不同!
保持謙卑,保持自信!
To Demut and Dottie!