一個(gè)多線程的Java程序,直到所有線程執(zhí)行完成,整個(gè)程序才會(huì)退出。(需要注意的是,是所有非后臺(tái)線程(non-daemon thread)執(zhí)行完成;如果一個(gè)線程執(zhí)行了System.exit()方法,程序也會(huì)退出。)有時(shí),你想中止一個(gè)線程的執(zhí)行,例如你想退出程序,或者你想取消一個(gè)正在執(zhí)行的任務(wù)等。
Java提供了中斷機(jī)制,可以讓我們顯式地中斷我們想中止執(zhí)行的線程。中斷機(jī)制的一個(gè)特征就是我們可以檢查線程是否已經(jīng)被中斷,進(jìn)而決定是否響應(yīng)中止請(qǐng)求。線程也可以忽略中止請(qǐng)求,繼續(xù)執(zhí)行。
在本節(jié),我們所開(kāi)發(fā)的示例程序?qū)?huì)創(chuàng)建一個(gè)線程,五秒鐘后,利用中斷機(jī)制強(qiáng)制中止這個(gè)線程。
知其然
按照下面步驟所示,完成示例程序。
1.創(chuàng)建一個(gè)名為PrimeGenerator的類,并且繼承Thread類。代碼如下:
public class PrimeGenerator extends Thread {
2.重寫(xiě)run()方法,在方法中添加一個(gè)無(wú)限循環(huán),在循環(huán)內(nèi),通過(guò)計(jì)算來(lái)檢查從1開(kāi)始的連續(xù)正整數(shù)是否為素?cái)?shù)。如果是,則打印到控制臺(tái)。代碼如下:
@Override
public void run() {
long number = 1L;
while (true) {
if (isPrime(number)) {
System.out.printf("Number %d \tis Prime.", number);
}
3.在處理一個(gè)數(shù)字之后,通過(guò)調(diào)用isInterrupted()方法來(lái)檢查線程是否被中斷。如果該方法返回true,則向控制臺(tái)打印一句話,然后中止線程執(zhí)行。代碼如下:
if (isInterrupted()) {
System.out.println("The Prime Generator has been Interrupted");
return;
}
number++;
}
}
4.實(shí)現(xiàn)isPrime()方法,該方法用于判斷參數(shù)是否為素?cái)?shù),如果是則返回true,否則返回false。代碼如下:
/**
* 判斷參數(shù)是否為素?cái)?shù)
*
* @param number 需要判斷的數(shù)字
* @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.現(xiàn)在,實(shí)現(xiàn)示例程序的主類,Main類,同時(shí)實(shí)現(xiàn)main()方法。代碼如下:
public class Main {
public static void main(String[] args) {
6.創(chuàng)建一個(gè)PrimeGenerator對(duì)象,并且啟動(dòng)該線程。代碼如下:
Thread task = new PrimeGenerator();
task.start();
7.等待五秒鐘,然后中止該線程。代碼如下:
try {
TimeUnit.SECONDS.sleep(5L);
} catch (InterruptedException e) {
e.printStackTrace();
}
task.interrupt();
8.運(yùn)行該示例,查看結(jié)果。
知其所以然
下面的是示例程序執(zhí)行的打印片段。我們從打印出的字符可以看出PrimeGenerator線程是如何打印輸出信息以及當(dāng)檢測(cè)到線程被中斷時(shí),如何中止其執(zhí)行的。
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有一個(gè)布爾型的熟悉,來(lái)表明線程是否被中斷。當(dāng)調(diào)用interrupt()方法時(shí),就是將其設(shè)置為true。而isInterrupted()方法則是返回該屬性的當(dāng)前值。
永無(wú)止境
Thread還有一個(gè)可以檢查線程是否中斷的方法:即靜態(tài)方法interrupted(),可以檢查當(dāng)前正在執(zhí)行的線程是否被中斷。
isInterrupted()方法和interrupted()方法有非常大的不同。前者不會(huì)改變線程是否中斷的屬性值;而后者則可以將其值設(shè)置為false。interrupted()是一個(gè)靜態(tài)方法;平時(shí)開(kāi)發(fā)推薦使用isInterrupted()方法。
正如前面所述,線程可以忽略中斷請(qǐng)求而繼續(xù)執(zhí)行。但是,這并不是我們想要的結(jié)果。
拿來(lái)主義
本文是從 《Java 7 Concurrency Cookbook》 (D瓜哥竊譯為 《Java7并發(fā)示例集》 )翻譯而來(lái),僅作為學(xué)習(xí)資料使用。沒(méi)有授權(quán),不得用于任何商業(yè)行為。
小有所成
示例程序所用的所有代碼的完整版本。
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++;
}
}
/**
* 判斷參數(shù)是否為素?cái)?shù)
*
* @param number 需要判斷的數(shù)字
* @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();
}
}