Java提供了一些控制線程執行順序的非常方便的工具方法,通過這些便捷的工具方法可以讓我們更加靈活地控制線程的執行。
今天我們主要討論控制線程的幾個常用方法:join、sleep、yield以及如何調整線程的優先順序。
Join線程
Thread提供了讓一個線程等待另一個線程完成之後自己再接著執行的方法:join方法。當某個程式執行流中調用其他線程的join方法時,調用線程將被阻塞,直到被join方法加入的join線程執行完成為止。
線程sleep
如果我們需要讓當前正在執行的線程暫停一段時間,並進入阻塞狀態,則可以通過調用Thread類的靜態方法sleep方法。
線程yield
yield方法是一個和sleep方法有點類似的方法,它也是一個Thread類提供的靜態方法,它也可以讓當前正在執行的線程暫停,但是它不會阻塞該線程,它只是將該線程轉入就緒狀態。yield只是讓當前線程暫停一下,讓系統的線程調度器重新調度一次,完全可能的情況是:當某個線程調用了yield方法暫停之後,線程調度器又再一次調度出來它重新執行。
實際上,當某個線程調用了yield方法暫停之後,只有優先順序與當前線程相同,或者優先順序比當前線程更高的就緒狀態的線程才有可能獲得執行的機會。
那麼sleep方法和yield方法的區別是什麼呢。
1sleep方法暫停當前線程後,會給其他線程執行的機會,不會關心其他線程的優先順序是否比當前線程高還是低。而yield方法則只會給優先順序相同或者優先順序更高的線程執行機會。
2sleep方法會將線程轉入阻塞狀態,直到經過阻塞時間才會轉入就緒狀態,而yield方法不經過阻塞狀態,直接強制進入就緒狀態。因此完全有可能某個線程調用了yield方法之後,立即再次獲得處理器資源接著執行。
3sleep方法聲明拋出InterruptedException異常,所以調用sleep方法時要麼捕捉該異常,要麼顯式聲明拋出該異常。而yield方法則沒有必要聲明拋出任何異常。
4sleep方法比yield方法有更好的移植性,通常不建議使用yield方法來控制並發線程的執行。
改變線程優先順序
在上文介紹yield方法時,提到了線程的優先順序。那麼線程的優先順序如何設定呢。
每個線程預設的優先順序都與建立它的父線程具有相同的優先順序,在預設情況下,main線程具有普通優先順序,由main線程建立的子線程也有普通優先順序。
Thread提供了setPriority(intnewPriority)和getPriority()方法來設定和返回指定線程的優先順序,其中setPriority方法的參數可以是一個整數,範圍為1-10之間,也可以使用Thread類的三個靜態常量:分別是MAX_PRIORITY=10,MIN_PRIORITY=1和NORM_PRIORITY=5。
後台進程
最後再來說一說這個後台進程,顧名思義就是在後台啟動並執行線程,他的任務是為其他的線程提供服務,這種線程被稱為Daemon Thread,又被稱為守護線程或者是精靈線程。JVM的記憶體回收線程就是典型的後台線程。後台線程有個特徵:如果所有的前台線程都死亡了,後台線程會自動死亡。
調用Thread對象的setDaemon(true)方法可以將指定線程設定成後台線程,但是需要注意的是setDaemon方法必須在start方法之前被調用,才可以成功設定為後台線程。還有一個用於判斷指定線程是否為後台進程的方法——isDaemon()。當整個虛擬機器中只剩下後台進程時,程式就沒有繼續啟動並執行必要了,所以虛擬機器也就退出了。