• 如何处理InterruptedException异常


    InterruptedException简单描述

    InterruptedException异常是一个经常被误解的异常,通常情况下我们会忽视或则转化成RuntimeException并抛出:throw new RuntimeException(e);然而这种做法通常都是不正确的。

    InterruptedException出现一般都是因为在线程执行的时候被打断(interrupt),线程(A)不是自己打断自己,一般都是在另外一个线程(B)中执行中断方法(objA.interrupt())。

    每个线程都管理一个自己的中断状态(interruption status),它可以通过Thread#interrupt()方法设置位中断状态,或则使Thread#interrupted()重置状态。另外,Thread#isInterrupted()通常用来判断是否处以中断状态。

    程序的状态

    RUNNABLE: 程序正在运行,其他线程能够调度它.
    BLOCKED, WAITING or TIMED_WAITING:线程等待中,等待一些像超时等事件的发生.

    当线程处于RUNNABLE状态的时候,通过Thread.currentThread.isInterrupted()判断中断状态,并终止程序循环执行:

    class ComplicatedCalculator implements Runnable {
      @Override
      public void run() {
        while (!Thread.currentThread.isInterrupted()) {
          // calculate something here
        }
      }
    }

    当线程处在BLOCKED, WAITING or TIMED_WAITING状态的时候,考虑以下程序,如何判断sleep正常执行完而没有被中断,也许可以通过sleep返回一个状态来判断,但是这增加了处理判断该状态的负担,所以sleep设计成了当抛出InterruptedException异常的方式来处理中断(这里拿Thread.sleep做示例,其他的也一样)。

    class Simulation implements Runnable {
      @Override
      public void run() {
        while (!Thread.currentThread.isInterrupted()) {
          // ... simulation calculations here ...
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            // empty
          }
        }
      }
    }

    处理InterruptedException异常的常用方法:

    • Rethrow:重新抛出,一般对blocking结果操作(如:BlockingQueue)直接重新抛出。
    class BlockQueueTest {
        ArrayBlockingQueue<Integer> testQueue = new ArrayBlockingQueue<Integer>(4);
    
        public int poll() throws InterruptedException {
            return testQueue.poll(10, TimeUnit.SECONDS);
        }
    
        public void put() throws InterruptedException {
            testQueue.put(1);
        }
    }
    • Catch, restore and terminate:像Runnable这种不能Rethrow异常,通常做法是catch异常,然后恢复中断状态,然后立即终止。
      注意: sleep被打断后会重置中断状态并抛出InterruptedException异常,也就是说当sleep catch住的代码块中,当前线程已经不是中断状态了,如果要终止程序,需要调用Thread.currentThread.interrupt(),Thread.currentThread.interrupt()就是将线程restore的意思了。
    class Simulation implements Runnable {
      @Override
      public void run() {
        while (!Thread.currentThread.isInterrupted()) {
          // ... simulation calculations here ...
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            // restore interruption status of the corresponding thread
            Thread.currentThread.interrupt();
          }
        }
      }
    }
    • Catch and terminate:这是上面一种方式的变种,像Thread的子类,已经是调用栈(不太懂)的最上层调用,没有人关系它的中中断状态,可以直接终止进程了。
      以下程序是我猜测这种处理方式的意思(不知道对不对):
    class Simulation extend Thread {
      @Override
      public void run() {
        while (true) {
          // ... simulation calculations here ...
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            // terminate
            return;
          }
        }
      }
    }

    个人感言(可以忽略):在方法或代码出现中断异常,如果不会对后面程序照成影响的话,我一般都记warn级别的日志(不知道对不对)。


    线程池中断线程

    通常情况下会通过调用Future#cancel(true)来发送中断请求。

    ExecutorService e = Executors.newFixedThreadPool(4);
    Future<?> f = e.submit(simulation);
    // ...
    // now cancel the running simulation
    f.cancel(true);

    参考文献

    http://daniel.mitterdorfer.name/articles/2015/handling-interruptedexception/

    转自:https://blog.csdn.net/kanbuqinghuanyizhang/article/details/52668978
     
  • 相关阅读:
    Servlet使用适配器模式进行增删改查案例(IBaseDaoUtil.java)
    Servlet使用适配器模式进行增删改查案例(BaseDao.java)
    Servlet使用适配器模式进行增删改查案例(Dept.java)
    Servlet使用适配器模式进行增删改查案例(Emp.java)
    sql server案例总结
    sql server操作案例
    java语音播报案例
    Java实现网络传输数据的压缩
    Java实现网络传输数据的压缩
    LZW压缩算法原理及其Java实现
  • 原文地址:https://www.cnblogs.com/javalinux/p/14298446.html
Copyright © 2020-2023  润新知