線程的Interrupt方法與InterruptedException解析


  1. 線程阻塞狀態與等待狀態(當一個線程處於被阻塞或等待狀態時,它暫時不活動,不允許任何代碼且消耗最少的資源)
    • 當一個線程試圖獲得一個內部的對象鎖(而不是java.util.concurrent庫中的鎖),而該鎖被其他線程持有,則該線程進入 阻塞狀態
    • 當一個線程等待另一個線程通知調度器的一個條件時,它自己進入 等待狀態。在調用Object.wait方法或Thread.join方法,或者是等待java.util.concurrent庫中的Lock或Condition時,就會出現這種情況。 實際上被阻塞狀態與等待狀態是有很大不同的
    • 帶有超時參數的方法,調用它們線程會進入 計時等待狀態。這一狀態將一直保持到超時期滿或者接收到適合的通知。帶有超時的方法有Thread.sleep、Object.wait、Thread.join、Lock.tryLock、Condition.await
  2. 沒有強制線程終止的方法。然而Interrupt方法可以用來請求終止線程,當對一個線程調用interrupt方法時,線程的 中斷狀態被置位,這是每一個線程都有的boolean狀態,每個線程應該不是的檢查這個標志,以判斷線程是否被中斷。當一個線程的中斷狀態被置位時,被中斷的線程決定如何響應中斷
    • intrrupt方法,用來中斷線程
    • interrupted是一個靜態方法,它檢測當前線程是否被中斷。而且, 該方法會清除該線程的中斷狀態,重置中斷狀態為false
    • isInterrupted是一個實例方法,檢驗是否有線程被中斷,不會改變中斷狀態
  3. 線程中斷時拋出InterruptedException異常解析
    • 當一個線程調在sleep方法時,如果在該線程上調用interrupt方法, 將拋出異常
    • 當一個線程進入一個同步阻塞( synchronize(o))的等待集wait時,調用interrupt方法, 將拋出異常
    • 當線程等待concurrent庫中鎖Lock時, 被中斷不拋異常
    • 當線程進入concurrent庫中條件等待集await時, 被中斷不拋異常
    • 如果在中斷狀態被置位時調用sleep方法,不會休眠, 反而會清除這一狀態(!)並拋出InterruptException異常
  4. 鎖測試與超時
    • 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();
       }
}

  

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM