網路程式經常使用到多執行緒程式設計,為讓初學者能夠輕鬆瞭解多執行緒的特色,以賽馬程式為範例,設計多執行緒的Java應用程式。依照內容順序實作,可瞭解到未使用多執行緒的問題與實作多執行緒的優點,並在最後進一步認識這個機制的特色與方法。
本篇為延續 Java的多執行緒,由基礎開始認識Threading ,請先認識執行緒的基礎。
繼承Thread類別
java.lang.Thread類別可以讓使用者向作業系統取得額外的執行緒,並在這個執行緒類別中,放入設計師想要做的工作。
設計執行緒類別
要產生一個執行緒得先要做好預先的設計工作,Thread類別中有個空的方法(裏面未有程式碼)叫做run(),開發人員可以新增一個類別並繼承Thread,再覆寫Thread的run()方法,將要執行的工作程式碼放在run()方法內,類別的架構如下圖。
產生執行緒類別並執行
上述的預先設計完成後擁有一個新的類別 Horse,將 Horse類別建構出來後,再呼叫其方法 start(),即可啟動這個執行緒,而這個執行緒將執行 run() 方法裏的工作。
package com. 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();
- 利用Thread類別建構子中的其中一個可接收參數Runnable物件的建構子
Thread thr = new Thread( h3 );
- 呼叫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類別的方法與控制執行緒的方法與活用。
後續文章:
Java的多執行緒之等待其他執行緒執行完成,三匹馬的賽事
版權聲明
本文章授權範圍僅限綠豆湯網站使用,除Facebook之類社群等未更改本文章出處之分享行為不在此限,其他個人或公司未經作者同意,不得任意將本文章內容轉載至其他網站,或以任何形式重製,為以免觸犯著作權法,請尊重作者之智慧財產權。
(1)Racing執行結果的2張圖是否貼反了?
(2)為何我不論Racing或Racing2每次執行的結果都一樣呢?
執行結果是對的,因為現在的電腦執行能力較好,可以試著加大迴圈數(如50000),才能看得出差異。