一個多執行緒的Java程序,直到所有執行緒執行完成,整個程式才會退出。 (需要注意的是,是所有非後台執行緒(non-daemon thread)執行完成;如果一個執行緒執行了System.exit()方法,程式也會退出。)有時,你會想中止一個執行緒的執行,例如你想退出程序,或者你想取消一個正在執行的任務等。
Java提供了中斷機制,可以讓我們明確地中斷我們想要中止執行的執行緒。中斷機制的一個特徵就是我們可以檢查執行緒是否已經中斷,進而決定是否回應中止請求。執行緒也可以忽略中止請求,繼續執行。
在本節,我們所開發的範例程式將會建立一個線程,五秒鐘後,利用中斷機制強制中止這個線程。
知其然
請依照下面步驟所示,完成範例程式。
1.建立一個名為PrimeGenerator的類,並且繼承Thread類別。程式碼如下:
複製代碼代碼如下:
public class PrimeGenerator extends Thread {
2.重寫run()方法,在方法中加入一個無限循環,在循環內,透過計算來檢查從1開始的連續正整數是否為質數。如果是,則列印到控制台。程式碼如下:
複製代碼代碼如下:
@Override
public void run() {
long number = 1L;
while (true) {
if (isPrime(number)) {
System.out.printf("Number %d /tis Prime.", number);
}
3.處理一個數字之後,透過呼叫isInterrupted()方法來檢查執行緒是否被中斷。如果該方法傳回true,則向控制台列印一句話,然後中止執行緒執行。程式碼如下:
複製代碼代碼如下:
if (isInterrupted()) {
System.out.println("The Prime Generator has been Interrupted");
return;
}
number++;
}
}
4.實作isPrime()方法,該方法用於判斷參數是否為質數,如果是則傳回true,否則傳回false。程式碼如下:
複製代碼代碼如下:
/**
* 判斷參數是否為質數
*
* @param number 需要判斷的數字
* @return
*/
private boolean isPrime(long number) {
if (number <= 2) {
return true;
}
for (int i = 2; i < number; i++) {
if ((number % i) == 0) {
return false;
}
}
return true;
}
5.現在,實作範例程式的主類,Main類,同時實作main()方法。程式碼如下:
複製代碼代碼如下:
public class Main {
public static void main(String[] args) {
6.建立一個PrimeGenerator對象,並且啟動該執行緒。程式碼如下:
複製代碼代碼如下:
Thread task = new PrimeGenerator();
task.start();
7.等待五秒鐘,然後中止該執行緒。程式碼如下:
複製代碼代碼如下:
try {
TimeUnit.SECONDS.sleep(5L);
} catch (InterruptedException e) {
e.printStackTrace();
}
task.interrupt();
8.運行該範例,查看結果。
知其所以然
下面的是範例程式執行的列印片段。我們從列印出來的字元可以看出PrimeGenerator執行緒是如何列印輸出資訊以及當偵測到執行緒被中斷時,如何中止其執行的。
複製代碼代碼如下:
Number 43063 is Prime.
Number 43067 is Prime.
Number 43093 is Prime.
Number 43103 is Prime.
Number 43117 is Prime.
The Prime Generator has been Interrupted
Thread有一個布林型的熟悉,來表示線程是否被中斷。當呼叫interrupt()方法時,就是將其設為true。而isInterrupted()方法則是傳回該屬性的目前值。
永無止境
Thread還有一個可以檢查執行緒是否中斷的方法:也就是靜態方法interrupted(),可以檢查目前正在執行的執行緒是否被中斷。
複製代碼代碼如下:
isInterrupted()方法和interrupted()方法有非常大的不同。前者不會改變線程是否中斷的屬性值;而後者則可以將其值設為false。 interrupted()是一個靜態方法;平常開發推薦使用isInterrupted()方法。
如前面所述,執行緒可以忽略中斷請求而繼續執行。但是,這並不是我們想要的結果。
拿來主義
本文是從《Java 7 Concurrency Cookbook》 (D瓜哥竊譯為《Java7並發範例集》 )翻譯而來,僅作為學習資料使用。沒有授權,不得用於任何商業行為。
小有所成
範例程式所用的所有程式碼的完整版本。
PrimeGenerator類別的完整程式碼複製程式碼如下:
package com.diguage.books.concurrencycookbook.chapter1.recipe3;
/**
* Date: 2013-09-18
* Time: 11:53
*/
public class PrimeGenerator extends Thread {
@Override
public void run() {
long number = 1L;
while (true) {
if (isPrime(number)) {
System.out.printf("Number %d /tis Prime./n", number);
}
if (isInterrupted()) {
System.out.println("The Prime Generator has been Interrupted");
return;
}
number++;
}
}
/**
* 判斷參數是否為質數
*
* @param number 需要判斷的數字
* @return
*/
private boolean isPrime(long number) {
if (number <= 2) {
return true;
}
for (int i = 2; i < number; i++) {
if ((number % i) == 0) {
return false;
}
}
return true;
}
}
Main類別的完整程式碼
複製代碼代碼如下:
package com.diguage.books.concurrencycookbook.chapter1.recipe3;
import java.util.concurrent.TimeUnit;
/**
* Date: 2013-09-18
* Time: 12:33
*/
public class Main {
public static void main(String[] args) {
Thread task = new PrimeGenerator();
task.start();
try {
TimeUnit.SECONDS.sleep(5L);
} catch (InterruptedException e) {
e.printStackTrace();
}
task.interrupt();
}
}