有時,我們需要在指定的時間點中斷正在執行的執行緒。例如,每分鐘檢查一次感測器狀態的線程,其餘時間,線程不需要做任何事情。在此期間,執行緒不需要使用電腦的任何資源。過了這段時間之後,當Java虛擬機器調度了該線程,則該線程繼續執行。為此,你可以使用Thread類別的sleeep()方法。此方法以休眠的方式來延遲執行緒的執行,而且整數類型的參數則指明休眠的毫秒數。當呼叫sleep()方法,休眠時間結束後,Java虛擬機器分配給執行緒CPU運行時間,執行緒就會繼續執行。
另一種是用sleep()方法的方式是透過枚舉型別TimeUnit的元素。此方式使用Thread的sleep()方法來使得目前執行緒進行休眠,它可以接受指定單位的時間作為參數,並將這些其轉換成對應的毫秒數。
在本節,我們將開發一個程序,使用sleep()方法來實現每秒鐘列印一次當前時間。
知其然
請依照下面所示步驟,來實作本節範例。
1.建立一個名為FileClock的類,並且實作Runnable介面。程式碼如下:
複製代碼代碼如下:
public class FileClock implements Runnable {
2.實作run()方法。程式碼如下:
複製代碼代碼如下:
@Override
public void run() {
3.寫一個遍歷十次的循環,在每次迭代中,建立一個Date對象,並將其列印到控制台。然後,透過TimeUtil的SECONDS屬性呼叫sleep()方法,來延遲一秒鐘執行緒。以為sleep()方法會拋出InterruptedException異常。所以,我們需要多寫幾行程式碼,用來捕捉異常。當執行緒可能中斷是,釋放或關閉在執行緒中使用的資源,總是最佳實踐。程式碼如下:
複製代碼代碼如下:
for (int i = 0; i < 10; i++) {
System.out.printf("%s/n", new Date());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.printf("The FileClock has been interrupted./n");
}
}
4.我們已經有了實作好的線程類別。現在,我們來實作主類別。建立一個名為FileMain的類,並且實作main()方法。程式碼如下:
複製代碼代碼如下:
public class FileMain {
public static void main(String[] args) {
5.建立一個FileClock對象,再建立一個執行緒用來執行任務。然後,啟動線程。程式碼如下:
複製代碼代碼如下:
FileClock clock = new FileClock();
Thread thread = new Thread(clock);
thread.start();
6.在主執行緒中,透過TimeUtil的SECONDS屬性呼叫sleep()方法,來等待五秒鐘。程式碼如下:
複製代碼代碼如下:
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
7.中斷FileClock線程。程式碼如下:
複製代碼代碼如下:
thread.interrupt();
8.執行範例,查看執行效果。
知其所以然
當執行這個程式時,會發現,程式如何每秒鐘列印一次日期對象,以及線程被中斷的情況。
當呼叫sleep()方法時,執行緒將離開CPU,並停止執行一段時間。在這段時間內,執行緒不需要CPU了,所以CPU可以執行其他任務。
當休眠中的執行緒被中斷時,會立即拋出一個InterruptedException,而不是等到休眠結束。
永無止境
在 Java並發API中,還有另一個方法可以讓執行緒讓出CPU。這就是yield()方法,呼叫該方法就是想Java虛擬機發送訊息說明執行緒可以讓出CPU給其他執行緒。 Java虛擬機器不保證回應這個請求。一般情況下,該方法僅在調試程式時使用。
拿來主義
本文是從《Java 7 Concurrency Cookbook》 (D瓜哥竊譯為《Java7並發範例集》 )翻譯而來,僅作為學習資料使用。沒有授權,不得用於任何商業行為。
小有所成
本節所用的範例程式碼的完整版。
FileClock類別的完整程式碼複製程式碼如下:
package com.diguage.books.concurrencycookbook.chapter1.recipe5;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* 每秒向控制台列印出目前日期和時間。
* Date: 2013-09-18
* Time: 23:11
*/
public class FileClock implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.printf("%s/n", new Date());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.printf("The FileClock has been interrupted./n");
}
}
}
FileMain類別的完整程式碼
複製代碼代碼如下:
package com.diguage.books.concurrencycookbook.chapter1.recipe5;
import java.util.concurrent.TimeUnit;
/**
* 演示線程休眠和恢復
* Date: 2013-09-19
* Time: 00:29
*/
public class FileMain {
public static void main(String[] args) {
FileClock clock = new FileClock();
Thread thread = new Thread(clock);
thread.start();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}