1. 程式人生 > 其它 >實現多執行緒的兩種方式

實現多執行緒的兩種方式

宣告

版權宣告:本文參考CSDN博主「一個快樂的野指標~」的原創文章,僅用作個人學習,特此宣告
原文連結:https://blog.csdn.net/qq_44715943/article/details/116714584

第一種方式

編寫一個類,直接 繼承 java.lang.Thread,重寫 run方法

  1. 怎麼建立執行緒物件? new繼承執行緒的類。
  2. 怎麼啟動執行緒呢? 呼叫執行緒物件的 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方法

  1. 怎麼建立執行緒物件? new執行緒類傳入可執行的類/介面。
  2. 怎麼啟動執行緒呢? 呼叫執行緒物件的 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);
        }
    }
}