资讯专栏INFORMATION COLUMN

Java中断异常 InterruptedException 的正确处理方式

diabloneo / 1928人阅读

摘要:首先,需要了解为一个方法为啥会是这个方法抛出中断异常作为方法签名的一部分以及调用正在调用的方法的可能结果。到目前为止,应该清楚的是,做这件事是一个坏主意。选择不同的接口,例如则可以抛出中断异常,或者按照说的上面的第二种方法。

你看到这篇文件可能是因为你已经调用了一个抛出 InterruptedException 异常的方法,并且需要以某种方式处理它。

首先,需要了解为一个方法为啥会 throws InterruptedException, 是这个方法抛出中断异常作为方法签名的一部分以及调用正在调用的方法的可能结果。因此,首先要接受一个事实,InterruptedException 是这个方法调用的完全有效的结果。

现在,如果你正在调用的方法抛出此类异常,你的方法应该怎么做?可以通过考虑以下问题找出答案:

你正在实现的方法是否有意义抛出异常 InterruptedException?换句话说,InterruptedException 异常是否是调用你的方法是一个明智的结果?

如果是,那么 throws InterruptedException 应当成为你的方法签名,你应该让异常传播(即不捕获该异常的话)。

示例: 你的方法等待来自网络的值以完成计算并返回结果。如果阻塞网络调用抛出 InterruptedException方法无法以正常方式完成计算。你让 InterruptedException 传播。

int computeSum(Server server) throws InterruptedException {
    // Any InterruptedException thrown below is propagated
    int a = server.getValueA();
    int b = server.getValueB();
    return a + b;
}

如果不是,那么你不应该声明你的方法 throws InterruptedException, 你应该(必须!)捕获异常。在这种情况下,现在要记住两件事:

有人打断了你的线程。这个人可能急于取消操作,优雅地终止程序,或者其他什么。你应该对那个人保持礼貌并且不用再费力地从你的方法中返回。

即使你的方法可以设法让出现 InterruptedException 异常时, 即在线程被中断的情况下, 产生合理的返回值,线程被中断过这件事仍然很重要。特别是,调用方法的代码可能会对执行方法期间是否发生中断感兴趣。您应该通过设置中断标志来记录发生中断的事实:即需要在 catch 里调用Thread.currentThread().interrupt() .

示例: 用户要求打印两个值的总和。如果无法计算总和,则打印“无法计算总和”(并且比由于一个导致程序因堆栈跟踪而崩溃要好得多 InterruptedException)。换句话说,用这个方法声明这个方法是没有意义的throws InterruptedException。

void printSum(Server server) {
    try {
        int sum = computeSum(server);
        System.out.println("Sum: " + sum);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();  // set interrupt flag
        System.out.println("Failed to compute sum");
    }
}

到目前为止,应该清楚的是,做这件事throw new RuntimeException(e)是一个坏主意。这对调用者来说不太礼貌。您可以发明一个新的运行时异常,但根本原因(某人希望线程停止执行)可能会丢失。

另一个例子:实施 Runnable
正如您可能已经发现的那样,签名 Runnable.run 不允许重新抛出 InterruptedExceptions。好吧,你声明了实现 Runnable 接口,这意味着你已声明处理可能的中断异常问题。选择不同的接口,例如Callable则可以抛出中断异常(V call() throws Exception),或者按照说的上面的第二种方法。

还有一个:调用 Thread.sleep
你正在尝试读取文件,规范说你应该尝试10次,间隔1秒。调用 Thread.sleep(1000)。所以,你需要处理 InterruptedException。对于一种方法 tryToReadFile 来说,如果说“如果我被打断了,我无法完成尝试阅读文件的行为”这一方法非常有意义。换句话说,它对抛出的方法很有意义InterruptedExceptions。

String tryToReadFile(File f) throws InterruptedException {
    for (int i = 0; i < 10; i++) {
        if (f.exists())
            return readFile(f);
        Thread.sleep(1000);
    }
    return null;
}


作者:

Andreas Lundblad,理论计算机科学博士。在Oracle开发Java平台(javac,javadoc,sjavac)工作了三年。安德烈亚斯是StackOverflow的Java标签的前10贡献者.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72633.html

相关文章

  • Java多线程笔记(一):JMM与基础关键字

    摘要:当线程执行完后进入状态,表示线程执行结束。其中和表示两个线程。但要注意,让出并不表示当前线程不执行了。关键字其作用是防止指令重排和使线程对一个对象的修改令其他线程可见。 JMM特性一览 Java Memory Model的关键技术点都是围绕着多线程的原子性、可见性和有序性来建立的。因此我们首先需要来了解这些概念。 原子性(Atomicity) 原子性是指一个操作是不可中断的。即使是在多...

    cyixlq 评论0 收藏0
  • Java多线程之线程创建、中断、状态与属性

    摘要:中断线程当线程的方法方法体执行完毕自然终止或在方法中出现没有捕获的异常时意外终止,线程将终止。如果被中断线程被阻塞,就无法检测中断状态,就会产生异常。 多进程与多线程的本质区别在于:每个进程拥有自己的一整套变量,而线程则共享数据。如果需要执行一个比较耗时的任务,应该使用独立的线程。 可以通过实现Runnable接口或继承Thread类来创建独立的线程。 1) 实现Ruannable接口...

    liangdas 评论0 收藏0
  • Java 多线程编程基础——Thread 类

    摘要:程序执行时,至少会有一个线程在运行,这个运行的线程被称为主线程。程序的终止是指除守护线程以外的线程全部终止。多线程程序由多个线程组成的程序称为多线程程序。线程休眠期间可以被中断,中断将会抛出异常。 线程 我们在阅读程序时,表面看来是在跟踪程序的处理流程,实际上跟踪的是线程的执行。 单线程程序 在单线程程序中,在某个时间点执行的处理只有一个。 Java 程序执行时,至少会有一个线程在运行...

    zhoutk 评论0 收藏0
  • java取消线程实例

    摘要:正确方法通过中断来取消线程。小结调用并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息。在使用静态的时应该小心,因为它会清除当前线程的中断状态。 序 本文展示一个常见的取消线程的方法。 错误实例 class BrokenPrimeProducer extends Thread { private final BlockingQueue queue; p...

    andot 评论0 收藏0
  • Thread类源码解读(3)——线程中断interrupt

    摘要:现在终止一个线程,基本上只能靠曲线救国式的中断来实现。中断机制的核心在于中断状态和异常中断状态设置一个中断状态清除一个中断状态方法同时会返回线程原来的中断的状态。中断异常中断异常一般是线程被中断后,在一些类型的方法如中抛出。 前言 系列文章目录 线程中断是一个很重要的概念,通常,取消一个任务的执行,最好的,同时也是最合理的方法,就是通过中断。 本篇我们主要还是通过源码分析来看看中断的概...

    fevin 评论0 收藏0

发表评论

0条评论

diabloneo

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<