實現多執行緒的兩種方式
阿新 • • 發佈:2022-04-18
宣告
版權宣告:本文參考CSDN博主「一個快樂的野指標~」的原創文章,僅用作個人學習,特此宣告
原文連結:https://blog.csdn.net/qq_44715943/article/details/116714584
第一種方式
編寫一個類,直接 繼承 java.lang.Thread,重寫 run方法。
- 怎麼建立執行緒物件? new繼承執行緒的類。
- 怎麼啟動執行緒呢? 呼叫執行緒物件的 start() 方法。
程式碼
public class ThreadTest { public static void main(String[] args) { MyThread t = new MyThread(); // 啟動執行緒 t.run(); // 不會啟動執行緒,不會分配新的分支棧。(這種方式就是單執行緒。) //t.start(); //這裡的程式碼還是執行在主執行緒中。 for(int i = 0; i < 5; i++){ System.out.println("主執行緒--->" + i); } } } class MyThread extends Thread { @Override public void run() { // 編寫程式,這段程式執行在分支執行緒中(分支棧)。 for(int i = 0; i < 10; i++){ System.out.println("分支執行緒--->" + i); } } }
注意
觀察上圖發現了一個問題,我已經建立了一個新的分支執行緒了,為什麼還是先走了run方法再走main方法呢?
原來java執行緒中,run方式和start方式是有區別的
run():在當前執行緒開啟,比如當前執行緒是主執行緒,那麼執行在主執行緒,如果當前執行緒是子執行緒,那麼在子執行緒執行。還是要順序執行,還是要等待run方法體執行完畢後才可繼續執行下面的程式碼,這樣就沒有達到寫執行緒的目的。
start():通過該方法啟動執行緒的同時也建立了一個執行緒,真正實現了多執行緒,這是無需等待run()方法中的程式碼執行完畢就可以直接執行執行緒外面的程式碼,通過start建立的執行緒處於可執行狀態,當得到CPU時間片後就會執行其中的run方法, 這裡方法run()稱為執行緒體,它包含了要執行的這個執行緒的內容,Run方法執行結束, 此執行緒隨即終止。
如下圖所示,run方法執行結束,此執行緒隨即終止
總結★★★★★
- t.run() 不會啟動執行緒,只是普通的呼叫方法而已。不會分配新的分支棧。(這種方式就是單執行緒。)
-
t.start() 方法的作用是:啟動一個分支執行緒,在JVM中開闢一個新的棧空間,這段程式碼任務完成之後,瞬間就結束了。這段程式碼的任務只是為了開啟一個新的棧空間,只要新的棧空間開出來,start()方法就結束了。執行緒就啟動成功了。啟動成功的執行緒會自動呼叫run方法,並且run方法在分支棧的棧底部(壓棧)。
run方法在分支棧的棧底部,main方法在主棧的棧底部。run和main是平級的。
注意:以下兩張圖片由原作者基於其原創程式碼
呼叫run()方法記憶體圖:
呼叫start()方法記憶體圖:
第二種方式:
編寫一個類,實現 java.lang.Runnable 介面,實現run方法。
- 怎麼建立執行緒物件? new執行緒類傳入可執行的類/介面。
- 怎麼啟動執行緒呢? 呼叫執行緒物件的 start() 方法。
注意:
第二種方式實現介面比較常用,因為一個類實現了介面,它還可以去繼承其它的類,更靈活。
普通方式
/**
* 實現執行緒的第二種方式
*/
public class ThreadTest2 {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
// 啟動執行緒
t.start();
for(int i = 0; i < 100; i++){
System.out.println("主執行緒--->" + i);
}
}
}
// 這並不是一個執行緒類,是一個可執行的類。它還不是一個執行緒。
class MyRunnable implements Runnable {
@Override
public void run() {
for(int i = 0; i < 100; i++){
System.out.println("分支執行緒--->" + i);
}
}
}
採用匿名內部類
/**
* 實現執行緒的第二種方式:採用匿名內部類
*/
public class ThreadTest3 {
public static void main(String[] args) {
// 建立執行緒物件,採用匿名內部類方式。
Thread t = new Thread(new Runnable(){
@Override
public void run() {
for(int i = 0; i < 100; i++){
System.out.println("t執行緒---> " + i);
}
}
});
// 啟動執行緒
t.start();
for(int i = 0; i < 100; i++){
System.out.println("main執行緒---> " + i);
}
}
}