1.如何終止一個線程
終止線程有三種方法
有三種方法可以使終止線程。
1. 使用退出標誌,使線程正常退出,也就是當run方法完成後線程終止。
2. 使用stop方法強行終止線程(這個方法不推薦使用,因爲stop和suspend、resume一樣,也可能發生不可預料的 結果)。 不推薦
3. 使用interrupt方法中斷線程。推薦
第一種方法終止線程(使用退出標誌,看註釋就好,註釋寫的很清楚了)
public class TestThread extends Thread{
//鎖住exit,保證當前只有一個線程能夠訪問並修改exit變量
//通過設置這個標誌來控制while循環是否退出
public volatile boolean exit = false;
public void run(){
while(!exit);
System.out.println("跳出循環了!");
}
public static void main(String[] args) throws Exception{
TestThread thread = new TestThread();
thread.start();
sleep(5000);//使當前線程延遲5秒後啓動(主線程)
thread.exit = true;//更改exit跳出while循環
thread.join();//讓調用該方法的thread完成run方法裏面的內容後,在執行join()方法後面的東西
System.out.println("線程退出!");
}
}
第二種方法終止線程使用stop方法可以強行終止正在運行或掛起的線程。我們可以使用如下的代碼來終止線程
thread.stop();
雖然使用上面的代碼可以終止線程,但使用stop方法是很危險的,就象突然關閉計算機電源,而不是按正常程序關機一樣,可能會產生不可預料的結果,因此,並不推薦使用stop方法來終止線程。(雖然筆者目前還沒有深入研究爲什麼可能會產生不可預料的結果,但是這裏希望大家有這個意識,不要使用這種方式強行終止一個線程,當然,具體原因有興趣的朋友可以再仔細閱讀JDK相關文檔)
第三種方法終止線程
使用interrupt方法終止線程
(1)線程處於阻塞狀態,如使用了sleep方法。
(2)使用while(!isInterrupted()){……}來判斷線程是否被中斷。
第一種情況(看註釋,註釋寫得很清楚了):
public class ThreadInterrupt extends Thread{
@Override
public void run() {
try {
sleep(50000);//該線程延遲50秒後執行
} catch (InterruptedException e) {
System.out.println(this.isInterrupted() + " " + e.getMessage());
}
}
public static void main(String[] args) throws Exception{
Thread thread = new ThreadInterrupt();
thread.start();
System.out.println(thread.isInterrupted());
System.in.read();//隨意輸入一些內容
thread.interrupt();//調用interrupt方法,使得sleep方法拋出一個interruptedException例外
System.out.println(thread.isInterrupted());//在異常尚未捕捉到時,看一下這個interrupted這個變量的值
thread.join();//使調用這個join的thread執行完run方法後,再執行後面的內容
System.out.println("線程已經退出");
}
}
我們看到,當線程調用interrupt方法後,檢測到的isInterrupted()方法的值爲true,但是捕獲到這個異常後isInterrupted()已經被重新置爲false了,即線程的狀態變爲非中斷狀態,那麼如果你的run中是一個循環的話,那麼如果catch語句沒有處理異常,則下一 次循環中isInterrupted()爲false,線程會繼續執行,可能你N次拋出異常,也無法讓線程停止,如下面的例子:
我們看到這裏,只是捕獲了異常,而沒有做相應的處理,導致線程仍舊再執行,如下:
我們看到這裏,只是捕獲了異常,而沒有做相應的處理,導致線程仍舊再執行,如下:
因此,我們可以使用一種叫做“二次惰性檢測(double check)”的方式,能在提高效率的基礎上又確保線程真正中同步控制中,即不以isInterrupted ()爲循環條件。而以一個標記作爲循環條件,如下:
public class ThreadB extends Thread{
private boolean isInterrupted=false;
int count=0;
public void interrupt(){
isInterrupted = true;
super.interrupt();
}
public void run(){
System.out.println(getName()+"將要運行...");
while(!isInterrupted){
System.out.println(getName()+"運行中"+count++);
try{
Thread.sleep(400);
}catch(InterruptedException e){
System.out.println(getName()+"從阻塞中退出...");
System.out.println("this.isInterrupted()="+this.isInterrupted());
}
}
System.out.println(getName()+"已經終止!");
}
public static void main(String[] args) throws Exception{
ThreadB tb=new ThreadB();
tb.setName("Thread b");
tb.start();
sleep(2000);
System.out.println(tb.getName()+"正在被中斷...");
tb.interrupt();
System.out.println("tb.isInterrupted()="+tb.isInterrupted());
}
}
輸出如下:
在這第二篇有關JAVA線程的內容,我就先說這麼多,也希望,無論是我寫的有問題還是對這裏的內容有疑惑,都希望大家提出來!