轉至:http://blog.csdn.net/anhuidelinger/article/details/11746365
終止線程的三種方法
有三種方法可以使終止線程。
1. 使用退出標誌,使線程正常退出,也就是當run方法完成後線程終止。
2. 使用stop方法強行終止線程(這個方法不推薦使用,因為stop和suspend、resume一樣,也可能發生不可預料的結果)。
3. 使用interrupt方法中斷線程。
1. 使用退出標誌終止線程
當run方法執行完後,線程就會退出。但有時run方法是永遠不會結束的。如在服務端程式中使用線程進行監聽用戶端請求,或是其他的需要迴圈處理的任務。在這種情況下,一般是將這些任務放在一個迴圈中,如while迴圈。如果想讓迴圈永遠運行下去,可以使用while(true){……}來處理。但要想使while迴圈在某一特定條件下退出,最直接的方法就是設一個boolean類型的標誌,並通過設定這個標誌為true或false來控制while迴圈是否退出。下面給出了一個利用退出標誌終止線程的例子。
package chapter2;
public class ThreadFlag extends Thread
{
public volatile boolean exit = false;
public void run()
{
while (!exit);
}
public static void main(String[] args) throws Exception
{
ThreadFlag thread = new ThreadFlag();
thread.start();
sleep(5000); // 主線程延遲5秒
thread.exit = true; // 終止線程thread
thread.join();
System.out.println("線程退出!");
}
}
在上面代碼中定義了一個退出標誌exit,當exit為true時,while迴圈退出,exit的預設值為false.在定義exit時,使用了一個Java關鍵字volatile,這個關鍵字的目的是使exit同步,也就是說在同一時刻只能由一個線程來修改exit的值,
2. 使用stop方法終止線程
使用stop方法可以強行終止正在運行或掛起的線程。我們可以使用如下的代碼來終止線程:
thread.stop();
雖然使用上面的代碼可以終止線程,但使用stop方法是很危險的,就象突然關閉電腦電源,而不是按正常程式關機一樣,可能會產生不可預料的結果,因此,並不推薦使用stop方法來終止線程。
3. 使用interrupt方法終止線程
使用interrupt方法來終端線程可分為兩種情況:
(1)線程處於阻塞狀態,如使用了sleep方法。
(2)使用while(。isInterrupted()){……}來判斷線程是否被中斷。
在第一種情況下使用interrupt方法,sleep方法將拋出一個InterruptedException例外,而在第二種情況下線程將直接退出。下面的代碼示範了在第一種情況下使用interrupt方法。
package chapter2;
public class ThreadInterrupt extends Thread
{
public void run()
{
try
{
sleep(50000); // 延遲50秒
}
catch (InterruptedException e)
{
System.out.println(e.getMessage());
}
}
public static void main(String[] args) throws Exception
{
Thread thread = new ThreadInterrupt();
thread.start();
System.out.println("在50秒之內按任意鍵中斷線程!");
System.in.read();
thread.interrupt();
thread.join();
System.out.println("線程已經退出!");
}
}
上面代碼的運行結果如下:
在50秒之內按任意鍵中斷線程!
sleep interrupted
線程已經退出!
在調用interrupt方法後, sleep方法拋出異常,然後輸出錯誤資訊:sleep interrupted.
注意:在Thread類中有兩個方法可以判斷線程是否通過interrupt方法被終止。一個是靜態方法interrupted(),一個是非靜態方法isInterrupted(),這兩個方法的區別是interrupted用來判斷當前線是否被中斷,而isInterrupted可以用來判斷其他線程是否被中斷。因此,while (。isInterrupted())也可以換成while (。Thread.interrupted())。
如何停止JAVA線程
如何停止java的線程一直是一個困惱我們開發多線程程式的一個問題。這個問題最終在Java5的java.util.concurrent中得到了回答:使用interrupt(),讓線程在run方法中停止。 簡介
在Java的多線程編程中,java.lang.Thread類型包含了一些列的方法start(), stop(), stop(Throwable) and suspend(), destroy() and resume()。通過這些方法,我們可以對線程進行方便的操作,但是這些方法中,只有start()方法得到了保留。
在Sun公司的一篇文章《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中詳細講解了捨棄這些方法的原因。那麼,我們究竟應該如何停止線程呢。 建議使用的方法
在《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? 》中,建議使用如下的方法來停止線程:
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
關於使用volatile關鍵字的原因,請查看http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#36930。 當線程處於非運行(Run)狀態
當線程處於下面的狀況時,屬於非運行狀態:
當sleep方法被調用。
當wait方法被調用。
當被I/O阻塞,可能是檔案或者網路等等。
當線程處於上述的狀態時,使用前面介紹的方法就不可用了。這個時候,我們可以使用interrupt()來打破阻塞的情況,如:
public void stop() { Thread tmpBlinker = blinker; blinker = null; if (tmpBlinker != null) { tmpBlinker.interrupt(); } }
當interrupt()被調用的時候,InterruptedException將被拋出,所以你可以再run方法中捕獲這個異常,讓安全執行緒退出:
try { .... wait();} catch (InterruptedException iex) { throw new RuntimeException("Interrupted",iex);}阻塞的I/O
當線程被I/O阻塞的時候,調用interrupt()的情況是依賴與實際啟動並執行平台的。在Solaris和Linux平台上將會拋出InterruptedIOException的異常,但是Windows上面不會有這種異常。所以,我們處理這種問題不能依靠於平台的實現。如:
package com.cnblogs.gpcusterimport java.net.*;import java.io.*;public abstract class InterruptibleReader extends Thread { private Object lock = new Object( ); private InputStream is; private boolean done; private int buflen; protected void processData(byte[] b, int n) { } class ReaderClass extends Thread { public void run( ) { byte[] b = new byte[buflen]; while (!done) { try { int n = is.read(b, 0, buflen); processData(b, n); } catch (IOException ioe) { done = true; } } synchronized(lock) { lock.notify( ); } } } public InterruptibleReader(InputStream is) { this(is, 512); } public InterruptibleReader(InputStream is, int len) { this.is = is; buflen = len; } public void run( ) { ReaderClass rc = new ReaderClass( ); synchronized(lock) { rc.start( ); while (!done) { try { lock.wait( ); } catch (InterruptedException ie) { done = true; rc.interrupt( ); try { is.close( ); } catch (IOException ioe) {} } } } }}
另外,我們也可以使用InterruptibleChannel介面。 實現了InterruptibleChannel介面的類可以在阻塞的時候拋出ClosedByInterruptException。如:
package com.cnblogs.gpcusterimport java.io.BufferedReader;import java.io.FileDescriptor;import java.io.FileInputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.nio.channels.Channels;public class InterruptInput { static BufferedReader in = new BufferedReader( new InputStreamReader( Channels.newInputStream( (new FileInputStream(FileDescriptor.in)).getChannel()))); public static void main(String args[]) { try { System.out.println("Enter lines of input (user ctrl+Z Enter to terminate):"); System.out.println("(Input thread will be interrupted in 10 sec.)"); // interrupt input in 10 sec (new TimeOut()).start(); String line = null; while ((line = in.readLine()) != null) { System.out.println("Read line:'"+line+"'"); } } catch (Exception ex) { System.out.println(ex.toString()); // printStackTrace(); } } public static class TimeOut extends Thread { int sleepTime = 10000; Thread threadToInterrupt = null; public TimeOut() { // interrupt thread that creates this TimeOut. threadToInterrupt = Thread.currentThread(); setDaemon(true); } public void run() { try { sleep(10000); // wait 10 sec } catch(InterruptedExcept