Java 多線程的創建
1. 前言
本節內容重點需要掌握 Java 多線程的三種創建方式,具體內容如下:
- Java 線程類 Thread 繼承結構,這是 JDK Thread 源碼的類結構,是了解 Thread 類的第一步;
- 掌握多線程的三種創建方式,這是本節的重點內容。本節所有內容都是圍繞改話題進行的講解;
- 了解多線程不同創建方式的優劣,不同的創建方式有自己的優勢和劣勢,本節還會推薦同學使用第二種接口實現的創建方式;
- 掌握 Thread 類常用方法,這也是本節的重點內容,其常用方法使我們開發過程中經常涉及到的,必須要熟記于心;
- Thread 類編程實驗實戰,學習完多線程的創建方式,我們需要進行實戰代碼鞏固本節的內容。
2. Thread 類結構介紹
介紹: 位于 java.lang 包下的 Thread 類是非常重要的線程類。學習 Thread 類的使用是學習多線程并發編程的基礎。它實現了 Runnable 接口,其包集成結構如下圖所示。
3. 多線程的三種創建方式
Java 多線程有 3 種創建方式如下:
- 方式一:繼承 Thread 類的方式創建線程;
- 方式二:實現 java.lang.Runnable 接口;
- 方式三:實現 Callable 接口。
在接下來的內容中,會詳細的對這 3 種創建方式進行詳細的講解。
4. 多線程實現之繼承 Thread 類
實現步驟:
- 步驟 1:繼承 Thread 類 extends Thread;
- 步驟 2:復寫 run () 方法,run () 方法是線程具體邏輯的實現方法。
實例:
/**
* 方式一:繼承Thread類的方式創建線程
*/
public class ThreadExtendTest extends Thread{ //步驟 1
@Override
public void run() { //步驟 2
//run方法內為具體的邏輯實現
System.out.println("create thread by thread extend");
}
public static void main(String[] args) {
new ThreadExtendTest(). start();
}
}
5. 多線程實現之實現 Runnable 接口
Tips:由于 Java 是面向接口編程,且可進行多接口實現,相比 Java 的單繼承特性更加靈活,易于擴展,所以相比方式一,更推薦使用方式二進行線程的創建。
實現步驟:
- 步驟 1:實現 Runnable 接口,implements Runnable;
- 步驟 2:復寫 run () 方法,run () 方法是線程具體邏輯的實現方法。
實例:
/**
* 方式二:實現java.lang.Runnable接口
*/
public class ThreadRunnableTest implements Runnable{//步驟 1
@Override
public void run() {//步驟 2
//run方法內為具體的邏輯實現
System.out.println("create thread by runnable implements");
}
public static void main(String[] args) {
new Thread(new ThreadRunnableTest()). start();
}
}
6. 多線程實現之實現 Callable 接口
Tips:方式一與方式二的創建方式都是復寫 run 方法,都是 void 形式的,沒有返回值。但是對于方式三來說,實現 Callable 接口,能夠有返回值類型。
實現步驟:
- 步驟 1:實現 Callable 接口,implements Callable;
- 步驟 2:復寫 call () 方法,call () 方法是線程具體邏輯的實現方法。
實例:
/**
* 方式三:實現Callable接口
*/
public class ThreadCallableTest implements Callable<String> {//步驟 1
@Override
public String call() throws Exception { //步驟 2
//call 方法的返回值類型是 String
//call 方法是線程具體邏輯的實現方法
return "create thread by implements Callable";
}
public static void main(String[] args) throws ExecutionException, InterruptedException{
FutureTask<String> future1 = new FutureTask<String>(new ThreadCallableTest());
Thread thread1 = new Thread(future1);
thread1. start();
System.out.println(future1.get());
}
}
7. 匿名內部類創建 Thread
首先確認,這并不是線程創建的第四種方式,先來看如何創建。
實例:
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("通過匿名內部類創建Thread");
}
});
我們從代碼中可以看出,還是進行了一個 Runnable 接口的使用,所以這并不是新的 Thread 創建方式,只不過是通過方式二實現的一個內部類創建。
Tips: 在后續章節講解 join 方法如何使用 的時候,我們會采用匿名內部類的方式進行多線程的創建。
8. Thread 類的常用方法介紹
方法 | 作用 |
---|---|
start() | 啟動當前的線程,調用當前線程的 run ()。 |
run() | 通常需要重寫 Thread 類中的此方法,將創建要執行的操作聲明在此方法中。 |
currentThread() | 靜態方法,返回代碼執行的線程。 |
getName() | 獲取當前線程的名字。 |
setName() | 設置當前線程的名字。 |
sleep(long millitime) | 讓當前進程睡眠指定的毫秒數,在指定時間內,線程是阻塞狀態。 |
isAlive() | 判斷進程是否存活。 |
wait() | 線程等待。 |
notify() | 線程喚醒。 |
9. Thread 編程測驗實驗
實驗目的:對 Thread 的創建方式進行練習,鞏固本節重點內容,并在練習的過程中,使用常用的 start 方法和 sleep 方法以及 線程的 setName 方法。
實驗步驟:
- 使用 Runnable 接口創建兩條線程 :t1 和 t2;
- 請設置線程 t1 和 t2 的線程名稱分別為 “ThreadOne” 和 “ThreadTwo”;
- 線程 t1 執行完 run () 方法后,線程睡眠 5 秒;
- 線程 t2 執行完 run () 方法后,線程睡眠 1 秒。
請先自行實現,并將結果與所提供的答案進行復核。
public class ThreadTest implements Runnable{
@Override
public void run() {
System.out.println("線程:"+Thread.currentThread()+" 正在執行...");
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new ThreadTest());
t1.setName("ThreadOne");
Thread t2 = new Thread(new ThreadTest());
t2.setName("ThreadTwo");
t1. start();
t1.sleep(5000);
t2. start();
t1.sleep(1000);
System.out.println("線程執行結束。");
}
}
執行結果:
線程:Thread[ThreadOne,5,main] 正在執行...
線程:Thread[ThreadTwo,5,main] 正在執行...
線程執行結束。
Tips: 該測驗主要針對線程的創建方式以及線程的執行 start 方法的測驗,并附帶進行了線程 setName 和線程 sleep 方法的使用。對于線程其他常用方法的使用如 wait 方法等,會在后續小節進行詳細講解。
10. 小結
本節課程的重中之重就是掌握線程的 3 中創建方式以及 Thread 類常用方法的使用,一定要掌握并吃透。
線程 Thread 的創建方式以及執行方式是學習多線程并發的前提條件,我們在使用無返回值的多線程創建方式時,推薦使用方式二進行多線程的創建。如果針對具體的業務場景需要使用多線程執行結果的返回值,那我們需要使用方式三進行線程的創建。