文章目錄
- 官網
- 方法&源碼
- void interrupt()
- ` boolean isInterrupted()` vs `static boolean interrupted()`
- 方法&示例
- void interrupt()
- sleep()方法中測試interrupt
- wait()方法中測試interrupt
- join方法中測試interrupt
- boolean isInterrupted() 和 static boolean interrupted()
官網
我們看下Java8中Thread類關于interrupt的幾個方法
先來看下基本用法,我們後面的例子再該示例上拓展
package com.artisan.test;
public class ThreadInterruptedDemo {
public static void main(String[] args) {
// 定義一個線程 死循環 調用start後一直運作
Thread t = new Thread(() -> {
while (true) {
}
}, "t");
// 啟動線程
t.start();
// 檢視t的狀态
System.out.println("before interrupt status>>>" + t.isInterrupted());
// interrupt
t.interrupt();
// 檢視t的狀态
System.out.println("after interrupt status>>>" + t.isInterrupted());
}
}
運作
方法&源碼
檢視官方的API,可以看到 關于interrupt的 我們可以調用的API 主要有3個
void interrupt()
----Interrupts this thread.
static boolean interrupted()
---Tests whether the current thread has been interrupted.
boolean isInterrupted()
----Tests whether this thread has been interrupted
void interrupt()
大緻意思是說:
除非目前線程正在中斷自身(始終允許),否則将調用此線程的checkAccess方法,這可能導緻抛出SecurityException。
如果在調用Object類的wait(),wait(long)或wait(long,int)方法,或者join(),join(long),join(long,int)方法中阻塞了這個線程,sleep(long)或sleep(long,int),這個類的方法,然後它的中斷狀态将被清除,它将收到InterruptedException。
如果在InterruptibleChannel上的I / O操作中阻塞了該線程,則該通道将被關閉,線程的中斷狀态将被設定,并且線程将收到ClosedByInterruptException。
如果此線程在Selector中被阻塞,則線程的中斷狀态将被設定,并且它将立即從選擇操作傳回,可能具有非零值,就像調用選擇器的喚醒方法一樣。
如果以前的條件都不成立,則将設定該線程的中斷狀态。
中斷不活動的線程不會産生任何影響
我們來看下源碼,我這裡标注了下注釋
public void interrupt() {
// 如果不是目前線程,抛出SecurityException異常
if (this != Thread.currentThread())
checkAccess();
// 對blockerLock對象加鎖 private final Object blockerLock = new Object();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // 調用interrupt0 這個native的方法 :Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
boolean isInterrupted()
vs static boolean interrupted()
boolean isInterrupted()
static boolean interrupted()
寫個例子 ,都在注釋裡了。
方法&示例
void interrupt()
sleep()方法中測試interrupt
package com.artisan.test;
public class ThreadInterruptedDemo {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) { // 捕獲InterruptedException
System.out.println(Thread.currentThread().getName() + " 接收到打斷信号 ");
e.printStackTrace();
}
}
}, "t");
t.start();
System.out.println("before interrupt status>>>" + t.isInterrupted());
// interrupt
t.interrupt();
System.out.println("after interrupt status>>>" + t.isInterrupted());
}
}
雖然捕獲了InterruptedException,但是該程式依舊還是運作,并沒有退出
wait()方法中測試interrupt
package com.artisan.test;
public class ThreadInterruptedDemo {
private static final Object MONITOR = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (true) {
// 使用wait的時候,必須要使用synchronized 加鎖
synchronized (MONITOR){
try {
MONITOR.wait(100);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " 接收到打斷信号 ");
e.printStackTrace();
}
}
}
}, "t");
t.start();
System.out.println("before interrupt status>>>" + t.isInterrupted());
// interrupt
t.interrupt();
System.out.println("after interrupt status>>>" + t.isInterrupted());
}
}
使用wait的時候,必須要使用synchronized 加鎖,這裡對一個Object對象加鎖
雖然捕獲了InterruptedException,但是該程式依舊還是運作,并沒有退出
join方法中測試interrupt
這個比較有意思,我們來逐漸的測試下
先搭個基本的架子
package com.artisan.test;
public class ThreadInterruptedDemo {
public static void main(String[] args) {
Thread t = new Thread(() -> {
while (true) {
}
}, "t");
// 啟動
t.start();
// join
try {
t.join();
} catch (InterruptedException e) {
System.out.println("收到中斷信号...");
e.printStackTrace();
}
System.out.println("這裡永遠都不會執行到,因為t是個死循環... ");
}
}
因為一旦 join方法執行了以後,後面的代碼都會被阻塞住,是以必須要在join之前開辟另外一個線程
為了直覺,我們直接貼圖吧
運作結果:
**并沒有出現我們期望的InterruptedException **,w t f…
我們來分析下,上面的兩個例子 。
sleep 我們sleep的是 t 線程,我們調用了
t.interrupt
,收到了
InterruptedException
wait 我們wait的也是t 線程,我們調用了
t.interrupt
,收到了
InterruptedException
但是我們join的時候,
t.join
,這個時候join的不是線程t,是join的main線程 ,是以必須用main線程來調用interrupt , 改造下
運作日志