一、LockSupport的park和unpark方法的基本使用,以及對線程中斷的響應性java
LockSupport是JDK中比較底層的類,用來建立鎖和其餘同步工具類的基本線程阻塞原語。java鎖和同步器框架的核心AQS:AbstractQueuedSynchronizer,就是經過調用LockSupport.park()和LockSupport.unpark()實現線程的阻塞和喚醒的。LockSupport很相似於二元信號量(只有1個許可證可供使用),若是這個許可尚未被佔用,當前線程獲取許可並繼續執行;若是許可已經被佔用,當前線程阻塞,等待獲取許可。注意:許可默認是被佔用的。框架
public static void main(String[] args) { ide
LockSupport.park(); 工具
System.out.println("block."); spa
} 線程
運行該代碼,能夠發現主線程一直處於阻塞狀態,不會輸出block.。由於許可默認是被佔用的,調用park()時獲取不到許可,因此進入阻塞狀態。須要注意的是,嘗試獲取許可證的是調用了 LockSupport.park()方法的線程。同步
LockSupport.unpark(Thread thread)方法須要傳入一個線程做爲參數,該方法的做用是容許做爲參數的線程獲取許可證,也就是喚醒做爲參數的線程。public static void main(String[] args) { string
Thread thread = Thread.currentThread(); it
LockSupport.unpark(thread);//釋放許可 io
LockSupport.park();// 獲取許可
System.out.println("b");
}
LockSupport是不可重入的,若是一個線程連續2次調用LockSupport.park(),那麼該線程必定會一直阻塞下去。
public static void main(String[] args) throws Exception {
Thread thread = Thread.currentThread();
LockSupport.unpark(thread);
System.out.println("a");
LockSupport.park();
System.out.println("b");
LockSupport.park();
System.out.println("c");
}
這段代碼打印出a和b,不會打印c,由於第二次調用park的時候,線程沒法獲取許可出現死鎖。
1.一、LockSupport對中斷的響應性
LockSupport.park()能響應中斷,也就是說A線程調用了LockSupport.park()方法被阻塞後,其餘線程調用了A線程的interrupt()方法給A線程發送中斷信號時,A線程的阻塞狀態會被中斷,繼續執行。固然了,調用了了某線程的interrupt()方法後,該線程的中斷狀態isInterrupted()會由false變爲true。
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
private int count = 0;
@Override
public void run() {
long start = System.currentTimeMillis();
long end = 0;
while ((end - start) <= 1000) {
count++;
end = System.currentTimeMillis();
}
System.out.println("after 1 second.count=" + count);
System.out.println("thread " + Thread.currentThread().isInterrupted());
//等待或許許可
LockSupport.park();
System.out.println("thread over." + Thread.currentThread().isInterrupted());
}
});
t.start();
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("向調用LockSupport.park()方法被阻塞的線程發送中斷信號");
// 中斷線程
t.interrupt();
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main over");
}
最終線程會打印出thread over.true。這說明線程若是由於調用LockSupport.park()而阻塞的話,可以響應中斷請求(中斷狀態被設置成true),可是不會拋出InterruptedException。
二、Thread詳解
isInterrupted() 只獲取線程的中斷狀態,返回值爲線程的中斷狀態(每一個線程都有一箇中斷狀態標誌位,用於代表當前線程是否處於中斷狀態)
interrupted() 獲取線程的中斷狀態,並清空狀態(即若是線程的中斷狀態爲true,則將其設置爲false;若是線程的中斷狀態爲false,則什麼也不作),返回值爲清空狀態前線程的中斷狀態
通常調用Thread的interrupt()會有兩種處理方式:
(1)遇到一個低優先級的block狀態時,好比object.wait(),object.sleep(),object.join()致使線程阻塞,它會立馬觸發一個unblock解除阻塞,並在線程阻塞的位置拋出一個InterruptedException,此時當前線程的中斷狀態標誌爲false
(2)其餘狀況致使的線程阻塞,Thread的interrupt()僅僅是更新了線程的中斷狀態標誌位。而後線程繼續執行,固然你也能夠經過Thread.isInterrrupted()進行檢查,作相應的處理,好比也拋出InterruptedException或者是清理狀態,取消task等。