Java 的多執行緒,以賽馬為例,如何繼承 Thread 與實作 Runnable 介面

Java 的多執行緒,以賽馬為例

網路程式經常使用到多執行緒程式設計,為讓初學者能夠輕鬆瞭解多執行緒的特色,以賽馬程式為範例,設計多執行緒的 Java 應用程式。依照內容順序實作,可瞭解到未使用多執行緒的問題與實作多執行緒的優點,並在最後進一步認識這個機制的特色與方法。

本篇為延續 Java 的多執行緒,由基礎開始認識 Threading ,請先認識執行緒的基礎。

繼承Thread類別

java.lang.Thread 類別可以讓使用者向作業系統取得額外的執行緒,並在這個執行緒類別中,放入設計師想要做的工作。

設計執行緒類別

要產生一個執行緒得先要做好預先的設計工作,Thread 類別中有個空的方法(裏面未有程式碼)叫做 run(),開發人員可以新增一個類別並繼承 Thread,再覆寫 Thread 的 run() 方法,將要執行的工作程式碼放在 run() 方法內,類別的架構如下圖。

java thread run

產生執行緒類別並執行

上述的預先設計完成後擁有一個新的類別 Horse,將 Horse 類別建構出來後,再呼叫其方法  start(),即可啟動這個執行緒,而這個執行緒將執行 run()  方法裏的工作。

public class Horse extends Thread{
  //覆寫Thread方法run()
  public void run(){
    //由1跑到5000
    int h = 0;
    for (int i=0; i<5000; i++){
      h++;
      System.out.println(getName()+":"+h);
    }
  }
} 

接下來,設計一個新類別 Racing 類別,在未開始執行迴圈之前,生出 Horse 類別的物件,再啟動這個執行緒:

public class Racing {
  public static void main(String[] args) {
    int h1 = 0;
    //產生Horse物件並啟動執行緒
    Horse h2 = new Horse();
    h2.start();
    for (int i=0; i<5000; i++){
      h1++;
      System.out.println("H1:"+h1);
    }
  }
} 

程式碼與執行緒之間的示意圖如下:

java thread main racing

多次執行結果不同

可以執行該程式多次,可看到執行結果的不同(每個人的結果可能不一樣),如下圖執行結果片段:

h2 執行緒比 main 還早執行完成

(省略)
H1:4995
H1:4996
H1:4997
H1:4998
H1:4999
H1:5000
Thread-0:1496
Thread-0:1497
Thread-0:1498
Thread-0:1499
(省略) 

main 執行緒較 h2 早執行完成

(省略)
Thread-0:4998
Thread-0:4999
Thread-0:5000
H1:1053
H1:1054
H1:1055
H1:1056
H1:1057
(省略) 

我們已設計一個新類別,並繼承 Thread 類別,然後覆寫了 run() 方法來產生執行緒,但有時候,一個已設計好的類別若已經繼承了其他父類別,而無法再繼承 Thread 類別時,則可以「實作 Runnable 介面」間接達成執行緒的設計。

實作 Runnable 介面

實作(implements)介面時,必須也要實作該介面的所有方法,Runnable 介面的唯一方法就是 run() 方法,將上一段的 Horse 改用介面來實作,新類別為HorseRunnable,由於 Runnable 與 Thread 都將執行緒的工作放在 run() 方法,因此,除了類別定義時改採為實作介面外,其他大致相同,設計方式如範例程式。

public class HorseRunnable implements Runnable{
    public void run(){
        int h = 0;
        for (int i=0; i<5000; i++){
            h++;
            System.out.println(h);
        }
    }
} 

啟動執行緒

要啟動實作 Runnable 介面的類別執行緒時,有些許的不同,利用三個步驟來啟動執行緒:

  1. 產生執行緒類別的物件
HorseRunnable h3 = new HorseRunnable(); 

2. 利用 Thread 類別建構子中的其中一個可接收參數 Runnable 物件的建構子

Thread thr = new Thread( h3 ); 

3. 呼叫 Thread 物件的 start() 方法

thr.start(); 

再另外設計一個 Racing2 類別,模擬兩匹馬的賽事,第二匹馬 h2 則是以 HorseRunnable 為執行緒,範例程式如下:

public class Racing2 {
    public static void main(String[] args) {
        int h1 = 0;
        //產生HorseRunnable物件並啟動執行緒
        HorseRunnable h2 = new HorseRunnable();
        Thread thr = new Thread(h2);
        thr.start();
        for (int i=0; i<5000; i++){
            h1++;
            System.out.println("H1:"+h1);
        }
    }
} 

執行結果與 Racing 類別大致類同,只是 HorseRunnable 未印出 H2 字樣。

在以繼承 Thread 與實作 Runnable 兩種方法後,下一篇文章,將以三匹馬的賽事實作案例,進一步認識 Thread 類別的方法與控制執行緒的方法與活用。

版權聲明

本文章授權範圍僅限綠豆湯網站使用,除 Facebook 之類社群等未更改本文章出處之分享行為不在此限,其他個人或公司未經作者同意,不得任意將本文章內容轉載至其他網站,或以任何形式重製,為以免觸犯著作權法,請尊重作者之智慧財產權。

1 Comment

  1. Noli

    老師,

    以前在文化大學旁聽過您的課,也有跟您發問問過問題
    但我相信您不記得我,我上過您FTP使用Java連線的課程
    非常謝謝您,開啟我對Java的興趣

    沒想到在網路上找文章又遇見您
    希望以後有機會能多上您的課程或購買您的書
    精通我的程式設計

    再次謝謝老師

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *