-
線程阻塞狀態與等待狀態(當一個線程處於被阻塞或等待狀態時,它暫時不活動,不允許任何代碼且消耗最少的資源)
-
當一個線程試圖獲得一個內部的對象鎖(而不是java.util.concurrent庫中的鎖),而該鎖被其他線程持有,則該線程進入 阻塞狀態
-
當一個線程等待另一個線程通知調度器的一個條件時,它自己進入 等待狀態。在調用Object.wait方法或Thread.join方法,或者是等待java.util.concurrent庫中的Lock或Condition時,就會出現這種情況。 實際上被阻塞狀態與等待狀態是有很大不同的
-
帶有超時參數的方法,調用它們線程會進入 計時等待狀態。這一狀態將一直保持到超時期滿或者接收到適合的通知。帶有超時的方法有Thread.sleep、Object.wait、Thread.join、Lock.tryLock、Condition.await
-
沒有強制線程終止的方法。然而Interrupt方法可以用來請求終止線程,當對一個線程調用interrupt方法時,線程的 中斷狀態被置位,這是每一個線程都有的boolean狀態,每個線程應該不是的檢查這個標志,以判斷線程是否被中斷。當一個線程的中斷狀態被置位時,被中斷的線程決定如何響應中斷
-
intrrupt方法,用來中斷線程
-
interrupted是一個靜態方法,它檢測當前線程是否被中斷。而且, 該方法會清除該線程的中斷狀態,重置中斷狀態為false
-
isInterrupted是一個實例方法,檢驗是否有線程被中斷,不會改變中斷狀態
-
線程中斷時拋出InterruptedException異常解析
-
當一個線程調在sleep方法時,如果在該線程上調用interrupt方法, 將拋出異常
-
當一個線程進入一個同步阻塞( synchronize(o))的等待集wait時,調用interrupt方法, 將拋出異常
-
當線程等待concurrent庫中鎖Lock時, 被中斷不拋異常
-
當線程進入concurrent庫中條件等待集await時, 被中斷不拋異常
-
如果在中斷狀態被置位時調用sleep方法,不會休眠, 反而會清除這一狀態(!)並拋出InterruptException異常
-
鎖測試與超時
-
tryLock方法試圖申請一個鎖,在成功獲得鎖后返回true,否則,立即返回false。而且線程可以離開去做其他事情
-
lock方法不能被中斷。如果一個線程在等待獲得一個鎖時被中斷,並不會拋出異常。中斷線程在獲得鎖之前一直處於阻塞狀態。如果出現死鎖,那么,lock方法就無法終止
-
然而,如果調用帶有超時參數的tryLock(1000,TimeUnit.MILLISECONDS),那么如果線程在等待期間被中斷, 將會拋出InterruptedException異常。這是一個非常有用的特性,因為允許程序打破死鎖
// 當一個線程調在sleep方法時,如果在該線程上調用interrupt方法 public class Demo { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(2000); System.out.println("end"); } catch (InterruptedException e) { e.printStackTrace(); } } }); t.start(); Thread.sleep(1000); t.interrupt(); // 拋出異常 } } // 當一個線程進入一個同步阻塞( synchronize(o))的等待集wait時 public class Demo { public Object o = new Object(); public void fun() throws InterruptedException { synchronized (o) { o.wait(); } } public static void main(String[] args) throws InterruptedException { Demo demo = new Demo(); Thread t = new Thread(new Runnable() { @Override public void run() { try { demo.fun(); System.out.println("end"); } catch (InterruptedException e) { e.printStackTrace(); } } }); t.start(); Thread.sleep(1000); t.interrupt(); // 拋出異常 } } // 當線程等待concurrent庫中鎖Lock時 public class Bank { private Lock bankLock; private Condition sufficientFunds; public Bank() { bankLock = new ReentrantLock(); sufficientFunds = bankLock.newCondition(); } public void transfer() throws InterruptedException { bankLock.lock(); // 線程t2不拋出異常,可能發生同步阻塞,建議使用帶超時的tryLock(1000,TimeUnit.MILLISECONDS),調用interrupt時拋出異常 // if (bankLock.tryLock()) // 線程t2獲取不到鎖,立即離開做其他事情 // if (bankLock.tryLock(3000, TimeUnit.MILLISECONDS)) // 線程t2拋出異常 // { try { while (true) { } } finally { bankLock.unlock(); } // } } public static void main(String[] args) throws InterruptedException { Bank bank = new Bank(); Thread t1 = new Thread(new Runnable() { @Override public void run() { try { bank.transfer(); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); bank.transfer(); System.out.println("end"); } catch (InterruptedException e) { e.printStackTrace(); } } }); t1.start(); t2.start(); Thread.sleep(2000); t2.interrupt(); } } // 當線程進入concurrent庫中條件等待集await時 public class Bank { private Lock bankLock; private Condition sufficientFunds; public Bank() { bankLock = new ReentrantLock(); sufficientFunds = bankLock.newCondition(); } public void transfer(boolean b,boolean c) throws InterruptedException { bankLock.lock(); try { if (b) sufficientFunds.await(); while (c) { } sufficientFunds.signalAll(); } finally { bankLock.unlock(); } } public static void main(String[] args) throws InterruptedException { Bank bank = new Bank(); Thread t1 = new Thread(new Runnable() { @Override public void run() { try { bank.transfer(true,false); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); bank.transfer(false,true); System.out.println("end"); } catch (InterruptedException e) { e.printStackTrace(); } } }); t1.start(); t2.start(); Thread.sleep(2000); t1.interrupt(); } }