要弄明白 interrupt,首先要了解如下幾點:java
Java中線程間是協做式,而非搶佔式. 調用一個線程的interrupt() 方法中斷一個線程,並非強行關閉這個線程,只是跟這個線程打個招呼,將線程的中斷標誌位置爲true,線程是否中斷,由線程自己決定。ide
isInterrupted() 斷定當前線程是否處於中斷狀態。spa
靜態方法 interrupted() 斷定當前線程是否處於中斷狀態,同時中斷標誌位改成 true。線程
若是方法裏若是拋出中斷異常 InterruptedException,則線程的中斷標誌位會被複位成false,若是確實是須要中斷線程,要求咱們本身在catch語句塊裏再次調用interrupt()。code
Java 中全部的阻塞方法都會拋出 InterruptedExceptionorm
public class EndThread {
private static class UseThread extends Thread{
public UseThread(String name) {
super(name);
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
while(true) {
System.out.println(threadName+" is run!");
}
//System.out.println(threadName+" interrput flag is "+isInterrupted());
}
}
public static void main(String[] args) throws InterruptedException {
Thread endThread = new UseThread("endThread");
endThread.start();
Thread.sleep(20);
endThread.interrupt();
}
}
複製代碼
運行結果:get
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
endThread is run!
...
複製代碼
endThread 一直在運行,主線程調用 interrupt() 方法並無使 endThread 真正中斷string
public class EndRunnable {
private static class UseRunnable implements Runnable{
@Override
public void run() {
String threadName = Thread.currentThread().getName();
while(Thread.currentThread().isInterrupted()) {
//若是真發生中斷後,這行代碼不會執行了
System.out.println(threadName+" is run!");
}
System.out.println(threadName+" interrupt flag is " +Thread.currentThread().isInterrupted());
}
}
public static void main(String[] args) throws InterruptedException {
UseRunnable useRunnable = new UseRunnable();
Thread endThread = new Thread(useRunnable,"endThread");
endThread.start();
Thread.sleep(20);
endThread.interrupt();
}
}
複製代碼
運行結果:it
endThread interrupt flag is false
複製代碼
經過 while(Thread.currentThread().isInterrupted()) 這種方式來控制循環能真正實現 interruptio
由上面兩個例子論證了Java中線程間是協做式,而非搶佔式
public class HasInterruptException {
private static SimpleDateFormat formater
= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss_SSS");
private static class UseThread extends Thread{
public UseThread(String name) {
super(name);
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
while(!isInterrupted()) {
try {
System.out.println("UseThread:"+formater.format(new Date()));
Thread.sleep(3000);
} catch (InterruptedException e) {
System.out.println(threadName + " catch interrput flag is "
+ isInterrupted() + " at "
+ (formater.format(new Date())));
//方法裏若是拋出InterruptedException,線程的中斷標誌位會被複位成false,
// 若是確實是須要中斷線程,要求咱們本身在catch語句塊裏再次調用interrupt()。
interrupt();
e.printStackTrace();
}
System.out.println(threadName);
}
System.out.println(threadName+" interrput flag is " +isInterrupted());
}
}
public static void main(String[] args) throws InterruptedException {
Thread endThread = new UseThread("HasInterrputEx");
endThread.start();
System.out.println("Main:"+formater.format(new Date()));
Thread.sleep(800);
System.out.println("Main begin interrupt thread:"+formater.format(new Date()));
endThread.interrupt();
}
}
複製代碼
運行結果:
UseThread:2019-09-10 15:06:57_995
Main:2019-09-10 15:06:57_995
Main begin interrupt thread:2019-09-10 15:06:58_795
HasInterrputEx catch interrput flag is false at 2019-09-10 15:06:58_795
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.xiangxue.ch1.safeend.HasInterrputException$UseThread.run(HasInterrputException.java:28)
HasInterrputEx
HasInterrputEx interrput flag is true複製代碼