java線程退出



在JDK1.0中,可以用stop方法來終止,但是現在這種方法已經被禁用了,改用interrupt方法。

Thread.interrupt()方法不會中斷一個正在運行的線程。它的作用是,在線程受到阻塞時拋出一箇中斷信號,這樣線程就得以退出阻塞的狀態。更確切的說,如果線程被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞,那麼,它將接收到一箇中斷異常(InterruptedException),從而提早地終結被阻塞狀態。

interrupt方法並不是強制終止線程,它只能設置線程的interrupted狀態,而在線程中一般使用一下方式:
while (!Thread.currentThread().isInterrupted() && more work to do)

{...}

而被block的線程(sleep() or join())在被調用interrupt時會產生InterruptException,此時是否終止線程由本線程自己決定。程序的一般形式是:
public void run()
{
try
{
. . .
while (!Thread.currentThread().isInterrupted() && more work to do)
{
do more work
}
}
catch(InterruptedException e)
{
// thread was interrupted during sleep or wait
}
finally
{
cleanup, if required
}
// exiting the run method terminates the thread
}

Thread.sleep方法也會產生InterruptedException,因此,如果每次在做完一些工作後調用了sleep方法,那麼就不用檢查isInterrupted,而是直接捕捉InterruptedException。

---------------------------------------------------------------------------------------

假如我們有一個任務如下,交給一個Java線程來執行,如何才能保證調用interrupt()來中斷它呢?

class ATask implements Runnable{

private double d = 0.0;

public void run() {
//死循環執行打印"I am running!" 和做消耗時間的浮點計算
while (true) {
System.out.println("I am running!");

for (int i = 0; i < 900000; i++) {
d = d + (Math.PI + Math.E) / d;
}
//給線程調度器可以切換到其它進程的信號
Thread.yield();
}
}
}

public class InterruptTaskTest {

public static void main(String[] args) throws Exception{
//將任務交給一個線程執行
Thread t = new Thread(new ATask());
t.start();

//運行一斷時間中斷線程
Thread.sleep(100);
System.out.println("****************************");
System.out.println("Interrupted Thread!");
System.out.println("****************************");
t.interrupt();
}
}


運行這個程序,我們發現調用interrupt()後,程序仍在運行,如果不強制結束,程序將一直運行下去,如下所示:
......
I am running!
I am running!
I am running!
I am running!
****************************
Interrupted Thread!
****************************
I am running!
I am running!
I am running!
I am running!
I am running!
....

雖然中斷髮生了,但線程仍然在進行,離開線程有兩種常用的方法:
拋出InterruptedException和用Thread.interrupted()檢查是否發生中斷,下面分別看一下這兩種方法:
1.在阻塞操作時如Thread.sleep()時被中斷會拋出InterruptedException(注意,進行不能中斷的IO操作而阻塞和要獲得對象的鎖調用對象的synchronized方法而阻塞時不會拋出InterruptedException)
Java代碼
class ATask implements Runnable{

private double d = 0.0;

public void run() {
//死循環執行打印"I am running!" 和做消耗時間的浮點計算
try {
while (true) {
System.out.println("I am running!");

for (int i = 0; i < 900000; i++) {
d = d + (Math.PI + Math.E) / d;
}
//休眠一斷時間,中斷時會拋出InterruptedException
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("ATask.run() interrupted!");
}
}
}

程序運行結果如下:
Java代碼
I am running!
I am running!
****************************
Interrupted Thread!
****************************
ATask.run() interrupted!

可以看到中斷任務時讓任務拋出InterruptedException來離開任務.

2.Thread.interrupted()檢查是否發生中斷.Thread.interrupted()能告訴你線程是否發生中斷,並將清除中斷狀態標記,所以程序不會兩次通知你線程發生了中斷.
Java代碼
class ATask implements Runnable{

private double d = 0.0;

public void run() {

//檢查程序是否發生中斷
while (!Thread.interrupted()) {
System.out.println("I am running!");

for (int i = 0; i < 900000; i++) {
d = d + (Math.PI + Math.E) / d;
}
}

System.out.println("ATask.run() interrupted!");
}
}

程序運行結果如下:
Java代碼
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
I am running!
****************************
Interrupted Thread!
****************************
ATask.run() interrupted!


我們可結合使用兩種方法來達到可以通過interrupt()中斷線程.請看下面例子:
Java代碼
class ATask implements Runnable{

private double d = 0.0;

public void run() {

try {
//檢查程序是否發生中斷
while (!Thread.interrupted()) {
System.out.println("I am running!");
//point1 before sleep
Thread.sleep(20);
//point2 after sleep
System.out.println("Calculating");
for (int i = 0; i < 900000; i++) {
d = d + (Math.PI + Math.E) / d;
}
}

} catch (InterruptedException e) {
System.out.println("Exiting by Exception");
}

System.out.println("ATask.run() interrupted!");
}
}

在point1之前處point2之後發生中斷會產生兩種不同的結果,可以通過修改InterruptTaskTest main()裏的Thread.sleep()的時間來達到在point1之前產生中斷或在point2之後產生中斷.
如果在point1之前發生中斷,程序會在調用Thread.sleep()時拋出InterruptedException從而結束線程.這和在Thread.sleep()時被中斷是一樣的效果.程序運行結果可能如下:
Java代碼
I am running!
Calculating
I am running!
Calculating
I am running!
Calculating
I am running!
****************************
Interrupted Thread!
****************************
Exiting by Exception
ATask.run() interrupted!

如果在point2之後發生中斷,線程會繼續執行到下一次while判斷中斷狀態時.程序運行結果可能如下:
Java代碼
I am running!
Calculating
I am running!
Calculating
I am running!
Calculating
****************************
Interrupted Thread!
****************************
ATask.run() interrupted!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章