线程的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();
       }
}

  

 
 
posted @ 2019-03-15 21:50  了不起的凤梨  阅读(1721)  评论(0编辑  收藏  举报