經過上篇的實例 線程在陷入阻塞時,在sychronized獲取互斥鎖陷入阻塞時,我們是無法進行中斷的,javase5中提供了一種解決的辦法 ReentrantLock ,我們常常用到的是它的lock()unlock方法,但是這里要重點說的是它的lockInterruptibly()方法 這種獲取鎖的方式,具備在獲取互斥鎖陷入阻塞時可以中斷該任務所在線程的能力,正常的lock()方法的運行機制是
嘗試獲取對象上的互斥鎖 若獲取成功,則標記該線程獲取到了鎖,然后返回,若獲取失敗,這時會將該線程阻塞並且放入等待獲取這個對象互斥鎖的隊列,然后開始循環競爭互斥鎖,若成功獲取到了鎖就會返回,若不成功則繼續放入等待隊列等待下一次競爭,一直到當前的線程獲取到了鎖,此時才會處理Interrupted標志,
而ockInterruptibly()獲取鎖的方式其實是稍稍有些改動 它是在每次競爭互斥鎖的時候都會檢查理Interrupted標志,若檢測到了之后就會處理中斷,所以具備競爭互斥鎖阻塞時,隨時可以中斷的能力。
下面演示一下實例
模擬兩個線程在爭搶一個對象上的互斥鎖
package test.thread.zhongjiahuayuan.interrupt.Lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** *演示ReentrantLock上阻塞的任務是可以被中斷的 * @author Administrator * */ public class BlockedMutex { private Lock lock = new ReentrantLock(); public BlockedMutex() { //獲取當前對象鎖 try { lock.lockInterruptibly(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void f(){ try { //獲取擋牆對象鎖 //這種獲取鎖的方式在等待獲取對象鎖 被阻塞的時候是可以被中斷的 lock.lockInterruptibly(); System.out.println("獲取對象鎖 在f()方法中"); } catch (InterruptedException e) { // TODO Auto-generated catch block System.out.println("中斷f"); } } } class Blocked2 implements Runnable{ BlockedMutex blocked = new BlockedMutex(); @Override public void run() { System.out.println("等待調用blocked的f方法"); blocked.f(); System.out.println("呼叫中斷"); } }
測試中斷
package test.thread.zhongjiahuayuan.interrupt.Lock; import java.util.concurrent.TimeUnit; public class Interrupting2 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new Blocked2()); t.start(); TimeUnit.SECONDS.sleep(1); System.out.println("Issuing t.interrupt()"); t.interrupt(); } }