Java線程停止方法之Interrupt方法
最近在學習Java多線程相關的知識點,其中關於線程停止的方法網上也有不少大牛給出了詳細的解答,而我這邊就其中Interrupt方法的注意點給自己提個醒。
首先還是大概的羅列下停止線程的方法:
1、使用stop()方法等,不過已經不再被推薦使用,和suspend、resume一樣。
2、使用退出標誌終止線程,引入一個共用變數,volatile類型或者使用synchronized來監視共用變數相關操作的方法,然後在run()方法中,通過while迴圈不停的輪詢這個標誌。
3、使用Interrupt方法中斷線程。
注意點:我一開始看到該方法的時候,認為interrupt會使線程停止運行,但事實上並非如此,調用一個線程的Interrupt方法會把線程的狀態改為中斷態。這其中又可以細分成兩個方面:
1)對於因執行了sleep、wait、join方法而休眠的線程:調用Interrupt方法會使他們不再休眠,同時會拋出 InterruptedException異常。比如一個線程A正在sleep中,這時候另外一個程式裡去調用A的interrupt方法,這時就會迫使A停止休眠而拋出InterruptedException異常,從而提前使線程逃離阻塞狀態。
2)對於正在啟動並執行線程,即沒有阻塞的線程,調用Interrupt方法就只是把線程A的狀態改為interruptted,但是不會影響線程A的繼續執行。
以下是對處於阻塞狀態線程使用Interrupt方法的例子:
class MyThread extends Thread {
volatile boolean stop = false;
public static void main( String args[] ) throws Exception {
MyThread thread = new MyThread();
System.out.println( "Starting thread..." );
thread.start();
Thread.sleep( 3000 );
System.out.println( "hread stop..." );
thread.stop = true; //如果線程阻塞,將不會檢查此變數
thread.interrupt();
Thread.sleep( 3000 );
System.out.println( "end..." );
}
public void run() {
while ( !stop ) {
System.out.println( "Thread running..." );
try {
Thread.sleep( 1000 );
} catch ( InterruptedException e ) {
System.out.println( "Thread interrupted..." );
}
}
System.out.println( "Thread exiting under request..." );
}
}
說明:對於被上述幾種方法阻塞的線程,正確的停止線程方式是設定共用變數,並調用interrupt()(注意變數應該先設定)。設定共用變數是為了沒有被阻塞的線程也能正常退出。
以下內容還在繼續研究中
在看一些博主的文章時還看到了一些特殊情況,也在這邊做個補充:
線程在I/O操作進行時被阻塞
分兩種情況:
1)使用通道(channels)的情況,通道是Java 1.4引入的I/O API,被阻塞的線程將收到一個ClosedByInterruptException異常。這與使用Interrupt方法拋出異常的用法一樣,只是異常不同而已。
2)使用傳統的I/O。
說明:即使Interrupt方法被調用了,Thread.interrupt()也不起作用,因為線程將不會退出被阻塞狀態。
解決辦法:調用阻塞該線程的通訊端的close()方法。在這種情形下,如果線程被I/O操作阻塞,該線程將接收到一個SocketException異常,這與使用interrupt()方法引起一個InterruptedException異常被拋出非常相似。 注意:唯一要說明的是,必須存在socket的引用(reference),只有這樣close()方法才能被調用。這意味著socket對象必須被共用。 以下代碼供參考:
class MyThread extends Thread {
volatile boolean stop = false;
volatile ServerSocket socket;
public static void main( String args[] ) throws Exception {
MyThread thread = new MyThread();
System.out.println( "Starting thread..." );
thread.start();
Thread.sleep( 3000 );
System.out.println( "Asking thread to stop..." );
thread.stop = true;
thread.socket.close();
Thread.sleep( 3000 );
System.out.println( "Stopping application..." );
}
public void run() {
try {
socket = new ServerSocket(7856);
} catch ( IOException e ) {
System.out.println( "Could not create the socket..." );
return;
}
while ( !stop ) {
System.out.println( "Waiting for connection..." );
try {
Socket sock = socket.accept();
} catch ( IOException e ) {
System.out.println( "accept() failed or interrupted..." );
}
}
System.out.println( "Thread exiting under request..." );
}
}
以上是自己對停止線程方法的一些總結,當然也是借鑒了不少博主的分享。重點放在了Interrupt方法,因為這邊容易理解出錯!