Java 的多執行緒,以賽馬為例
網路程式經常使用到多執行緒程式設計,為讓初學者能夠輕鬆瞭解多執行緒的特色,以賽馬程式為範例,設計多執行緒的 Java 應用程式。依照內容順序實作,可瞭解到未使用多執行緒的問題與實作多執行緒的優點,並在最後進一步認識這個機制的特色與方法。
本篇為延續 Java 的多執行緒,由基礎開始認識 Threading ,請先認識執行緒的基礎。
繼承Thread類別
java.lang.Thread 類別可以讓使用者向作業系統取得額外的執行緒,並在這個執行緒類別中,放入設計師想要做的工作。
設計執行緒類別
要產生一個執行緒得先要做好預先的設計工作,Thread 類別中有個空的方法(裏面未有程式碼)叫做 run(),開發人員可以新增一個類別並繼承 Thread,再覆寫 Thread 的 run() 方法,將要執行的工作程式碼放在 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);
}
}
}
程式碼與執行緒之間的示意圖如下:
多次執行結果不同
可以執行該程式多次,可看到執行結果的不同(每個人的結果可能不一樣),如下圖執行結果片段:
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 介面的類別執行緒時,有些許的不同,利用三個步驟來啟動執行緒:
- 產生執行緒類別的物件
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 之類社群等未更改本文章出處之分享行為不在此限,其他個人或公司未經作者同意,不得任意將本文章內容轉載至其他網站,或以任何形式重製,為以免觸犯著作權法,請尊重作者之智慧財產權。
老師,
以前在文化大學旁聽過您的課,也有跟您發問問過問題
但我相信您不記得我,我上過您FTP使用Java連線的課程
非常謝謝您,開啟我對Java的興趣
沒想到在網路上找文章又遇見您
希望以後有機會能多上您的課程或購買您的書
精通我的程式設計
再次謝謝老師