瀏覽以下內容前,請點擊並閱讀 聲明
線程對象
每個線程都和類Thread的實例相關,有兩種基本的使用Thread對象來創建並發應用的方法:
- 直接控制線程的創建和管理,每次需要開始一個異步任務時簡單地實例化Thread類。
- 從你的程序中轉移線程的管理,將應用的任務傳遞給一個執行程序。
本章主要討論Thread類。
定義並啟動一個線程
創建一個線程對象必須提供線程中執行的代碼,實現的方法有兩種:
- 實現Runnable接口,Runnable接口定義了一個run方法,該方法中含有在線程中執行的方法,Runnable對象作為參數傳遞給Thread類的構造器來創建新的Thread實例,如下所示:
public class HelloRunnable implements Runnable { public void run() { System.out.println("Hello from a thread!"); } //以下主方法創利用定義的Runnable的實現類建類一個線程對象 public static void main(String args[]) { (new Thread(new HelloRunnable())).start(); } }
- 繼承Thread類,Thread類自身是實現Runnable接口的,盡管其run方法不執行任何操作,一個類可以繼承Thread類,覆寫run方法,如下所示:
public class HelloThread extends Thread { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { (new HelloThread()).start(); } }
兩個例子中,調用Thread實例中的start方法的作用就是啟動新創建的線程。
對於這兩種方法我們使用那種呢?第一種方法使用更為廣泛一些,因為實現Runnable后不僅可以創建新的線程,而且還可以繼承除Thread的其他類。而第二種用法在簡單的應用中則更為快捷,但是不能再繼承其他類。以下舉例都用第一種方法,因為該方法更加靈活,更重要的是其適用於更高級的線程管理API。
用sleep方法暫停執行
Thread.sleep方法會導致當前的線程暫停指定的時間。這個方法在需要將處理器時間交給其他線程或進程的時候比較有效。
sleep方法由兩個重載的版本,一個指定休眠的毫秒數,另外一個指定休眠的納秒數,當然,時間不一定精確,計時是由底層的操作系統決定的,睡眠期間可以終止,因此任何時候,你都不要指望sleep方法能夠暫停你指定的時間長度。
中斷
中斷是指示一個線程停下當前所做的事情去做另外一件事,一個線程對於中斷的反應是由程序員決定的,不過一般都是終止該線程。通過調用一個線程對象的interrupt方法,可以中斷該線程,為了使中斷機制正常運行,被中斷的線程必須支持自身的中斷。
支持中斷
要使一個線程支持中斷,則要在確保在線程接受到中斷指示時從run方法返回,如果該線程經常調用一些拋出InterruptedException
的方法,那么捕獲InterruptedException
后,就應該使用return語句返回,如果沒有使用拋出中斷異常的方法,則要使用定期使用Thread.interrupted方法判斷該線程是否被中斷,如果中斷,使用return語句返回:
for (int i = 0; i < inputs.length; i++) { heavyCrunch(inputs[i]); if (Thread.interrupted()) { //如果被中斷,則返回 return; } }
中斷狀態標志
中斷機制是用一個內部的標志,叫做中斷狀態實現的,調用Thread.interrupt
方法將設定該標志,當通過一個靜態方法Thread.interrupt
ed來檢查中斷狀態時,中斷狀態會被清除,非靜態方法isInterrupted,一個線程用來檢查另外一個線程的中斷狀態的,該方法不會改變中斷狀態。
在一個線程中,所有因拋出InterruptedException
而返回的方法都會清除中斷狀態,但不排除之后立馬會有其他線程設置其中斷狀態。
join方法
join方法的使用允許一個線程等待另一個線程執行完畢,如果t是一個當前正在執行的Thread對象,則:
t.join();
以上方法會讓當前的線程暫停執行直到t執行完畢為止。join方法還有另外一個重載的版本,可以加入參數指定最長的等待時間,超過該時間后將不再等待。和sleep一樣,其時間的准確性由系統而定,同時能對中斷響應。