三匹馬的賽事
設計多執行緒 Threading 程式時,常需要等待其他執行緒的執行結果,收集資訊後再進一步處理,本文章延續上一篇文章:
Java 的多執行緒,以賽馬為例,如何繼承 Thread 與實作 Runnable 介面
在上一篇文章中,以 main 執行緒為第一匹馬,另外以 Horse 執行緒為第二匹馬,現在想讓 main 方法專心處理產生執行緒與計算賽馬名次等工作,因此,改變為三匹馬都以 Horse 執行緒來執行,在 main 方法中產生三個 Horse 執行緒物件,利用 Thread 的方法 setName() 給予三匹馬執行緒名稱(h1, h2, h3),main 方法執行到最後時,印出「main 執行緒結束」:
sleep 方法
為了方便觀察 Horse 執行緒的執行結果,將原 for 迴圈改為讓執行緒睡覺 2 秒鐘,可使用 Thread 的方法 sleep(long millis),共 2000 毫秒,sleep 方法使用時必須以 try…catch 處理被意外中斷的例外 InterruptedException:
執行 Racing3 類別的結果如下(每次結果有可能不一樣):
發現一個問題了嗎?就是 main 執行緒是三匹馬執行緒的發起者,但它卻比三匹馬執行緒還要早結束,若是如此,我們將無法在三匹馬跑出結果時印出到達順序,如何能讓 main 執行緒等待三匹馬執行緒都結束後,才繼續往後執行呢?
如果讓 main 執行緒進入睡眠一段時間,雖然可以在睡醒時進行後續的動作,但如果睡覺時間不夠準確,或是三匹馬的執行緒完成時間是未知時,sleep() 方法也就不適合用來等待其他「子執行緒」,因此,可以利用 join() 方法達到等待其他執行緒完成後,再進行後續的動作。
join() 方法-等待
Thread 類別的方法 join(),可以用來等待該執行緒完成,使用 join() 方法時,和 sleep() 方法一樣,必須以 try…catch 處理被意外中斷的例外 InterruptedException,如下:
觀察執行結果可發現,main 執行緒會等待三匹馬執行緒都完成後,才會繼續第 21 行的執行:
結算賽馬的名次
瞭解如何利用 join() 方法來等待子執行緒之後,先訂定一個放置三匹馬的集合 rank,第一匹到達的馬可以進入到 rank 集合的第 1 個位置,第二匹到達的馬則進入到 rank 集合的第 2 的位置,以此類推。使用 java.util.ArrayList 做為集合類別,新增一類別 Racing4 來設計此功能:
上述程式碼第 7 行,新增一個 List 物件 rank,而且以「一般化」限定 rank 集合裏只能放置 RankHorse 物件,第 8-10 行則利用 RankHorse 的建構子將 rank 物件傳遞給執行緒類別 RankHorse 內部使用,最後在第 24 行依序印出 rank 集合內的所有物件(三匹馬)。因此,我們還要依照先前 Horse 類別的模式,再設計 RankHorse 類別,使其擁有排名的功能,範例程式如下:
上述程式的第 4 行,定義了成員 rank,第 6-8 行則新增了建構子,以接收 Racing4 所傳來的 rank 物件,最後,等到此匹馬到達終點時,第 17 行將自己放入 rank 集合中,若此匹馬是第一名到達,將會放置在第一位。
Racing4 類別的執行結果如下,可以看到 rank 集合內依照到達順序的三匹馬:
集合內的每匹 RankHorse 的 h1, h2, h3 是執行緒的名稱,接著逗號後跟著該執行緒的優先權值,預設是 5,有關執行優先權之後再另以文章介紹。
版權聲明
本文章授權範圍僅限綠豆湯網站使用,除 Facebook 之類社群等未更改本文章出處之分享行為不在此限,其他個人或公司未經作者同意,不得任意將本文章內容轉載至其他網站,或以任何形式重製,為以免觸犯著作權法,請尊重作者之智慧財產權。