首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 多執行緒核心:Runnable 與 Thread 差異深度解析

     編輯:Java 相關知識

兩種實作多執行緒的方式

Java 提供兩種建立執行緒的主要途徑:繼承 Thread 類別與實作 Runnable 介面。兩者在語法、設計彈性、資源共享上有本質差異。

方式一:繼承 Thread 類別

class MyThread extends Thread {
    private String name;
    public MyThread(String name) { this.name = name; }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("執行緒:" + name + ", i=" + i);
        }
    }
}

// 啟動
MyThread mt1 = new MyThread("執行緒A");
MyThread mt2 = new MyThread("執行緒B");
mt1.start(); // 必須呼叫 start(),而非 run()
mt2.start();

關鍵點:start() 會請求 JVM 配置新執行緒並呼叫 run();直接呼叫 run() 只是單執行緒循序執行。Thread 內部透過 native 方法 start0() (JNI) 與作業系統互動。

方式二:實作 Runnable 介面

class MyRunnable implements Runnable {
    private String name;
    public MyRunnable(String name) { this.name = name; }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("執行緒:" + name + ", i=" + i);
        }
    }
}

// 啟動:將 Runnable 實例傳給 Thread 建構子
new Thread(new MyRunnable("執行緒A")).start();
new Thread(new MyRunnable("執行緒B")).start();

核心差異對比

比較項目繼承 Thread實作 Runnable
繼承限制單一繼承,無法繼承其他類別可實作多個介面,彈性高
資源共享每個 Thread 實例擁有獨立屬性,難以共享同一 Runnable 實例可傳給多個 Thread,天然共享資料
耦合度執行緒邏輯與控制耦合職責分離:Runnable 負責任務,Thread 負責調度
適用場景簡單、獨立的執行緒任務複雜系統、需共享資料、線程池

賣票案例:資源共享的實證

Thread 版本(無法共享)

class TicketThread extends Thread {
    private int tickets = 10; // 每個實例各有 10 張
    public void run() {
        for (int i = 0; i < 20; i++) {
            if (tickets > 0) System.out.println("賣票:" + tickets--);
        }
    }
}
new TicketThread().start(); // 各賣 10 張,總共 30 張
new TicketThread().start();
new TicketThread().start();

Runnable 版本(真正共享)

class TicketRunnable implements Runnable {
    private int tickets = 10; // 單一實例共享
    public void run() {
        for (int i = 0; i < 20; i++) {
            if (tickets > 0) System.out.println("賣票:" + tickets--);
        }
    }
}
TicketRunnable task = new TicketRunnable();
new Thread(task).start(); // 總共只賣 10 張
new Thread(task).start();
new Thread(task).start();

原始碼層面的關聯

public class Thread extends Object implements Runnable { ... }

Thread 本身實作了 Runnable,這也是為什麼 Thread 建構子可以接受 Runnable 參數的原因。

最佳實務建議

  1. 優先使用 Runnable:符合「組合優於繼承」原則,支援線程池 (ExecutorService) 與 Lambda 表達式 (Java 8+)。
  2. 避免直接繼承 Thread:除非需要覆寫 Thread 的其他方法(如 getId()、interrupt() 處理)。
  3. 共享資料時注意同步:Runnable 共享資料易產生競態條件,需配合 synchronized、Lock、AtomicInteger 等機制。

總結

Runnable 與 Thread 的選擇不只是語法偏好,更關乎系統架構的彈性與正確性。理解兩者在資源共享、繼承限制、耦合度上的差異,是撰寫高品質多執行緒程式的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved