GVKun编程网logo

为什么要捕获InterruptedException来调用Thread.currentThread.interrupt()?(为什么要捕获异常)

29

本文将介绍为什么要捕获InterruptedException来调用Thread.currentThread.interrupt的详细情况,特别是关于?的相关信息。我们将通过案例分析、数据研究等多种方

本文将介绍为什么要捕获InterruptedException来调用Thread.currentThread.interrupt的详细情况,特别是关于的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于&Thread线程:中断异常InterruptedException、C3P0:java.lang.InterruptedException: sleep interrupted、InterruptedException: sleep interrupted at java.lang.Thread.sleep、java – 为什么在实现Runnable时使用Thread.currentThread().isInterrupted()而不是Thread.interrupted()?的知识。

本文目录一览:

为什么要捕获InterruptedException来调用Thread.currentThread.interrupt()?(为什么要捕获异常)

为什么要捕获InterruptedException来调用Thread.currentThread.interrupt()?(为什么要捕获异常)

在有效的Java(第275页)中,有以下代码段:

...for (int i = 0; i < concurrency; i++) {  executor.execute(new Runnable() {    public void run() {    ready.countDown();    try {      start.await();      action.run();    } catch (InterruptedException e) {      Thread.currentThread().interrupt();    } finally {      done.countDown();    }  }}...

捕获中断异常以重新引发它有什么用?为什么不让它飞呢?

答案1

小编典典

简单的答案是,这InterruptedException是一个检查的异常,它不在Runnable.run方法(或Executable.execute()方法)的签名中。所以你必须抓住它。一旦发现它,Thread.interrupt()建议您设置为设置中断标志。除非您确实打算压缩中断。

&Thread线程:中断异常InterruptedException

&Thread线程:中断异常InterruptedException

方法讲解

Java Doc定义:
Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. Occasionally a method may wish to test whether the current thread has been interrupted, and if so, to immediately throw this exception.
意思:当一个线程处于等待,睡眠,或者占用,也就是说阻塞状态,而这时线程被中断就会抛出这类错误。Java6之后结束某个线程A的方法是A.interrupt()。如果这个线程正处于非阻塞状态,比如说线程正在执行某些代码的时候,不过被interrupt,那么该线程的interrupt变量会被置为true,告诉别人说这个线程被中断了(只是一个标志位,这个变量本身并不影响线程的中断与否),而且线程会被中断,这时不会有interruptedException。但如果这时线程被阻塞了,比如说正在睡眠,那么就会抛出这个错误。请注意,这个时候变量interrupt没有被置为true,而且也没有人来中断这个线程。

 

  1. public static boolean interrupted();// 检测当前线程是否已经中断,此方法会清除中断状态,也就是说,假设当前线程中断状态为true,第一次调此方法,将返回true,表明的确已经中断了,但是第二次调用后,将会返回false,因为第一次调用的操作已将中断状态重新置为false了。
  2. public boolean isInterrupted() ;// 检测当前线程是否已经中断,此方法与上一方法的区别在于此方法不会清除中断状态。
  3. public void interrupt();//将线程中断状态设置为true,表明此线程目前是中断状态。此时如果调用isInterrupted()方法,将会得到true的结果。

结论:interrupt方法本质上不会进行线程的终止操作的,它不过是改变了线程的中断状态,将线程中断状态设置为true。而改变了此状态带来的影响是,部分可中断的线程方法(比如Object.wait, Thread.sleep,Object.join)会定期执行isInterrupted方法,检测到此变化,随后会停止阻塞并抛出InterruptedException异常,并且在抛出异常后立即将线程的中断标示位清除,即重新设置为false。

案例分析:
public class InterruptedException {
    public static void main(String[] args) throws Exception {
        System.out.println("初始中断状态:" + Thread.currentThread().isInterrupted());
        Thread.currentThread().interrupt();
        System.out.println("执行完interrupt方法后,中断状态:" + Thread.currentThread().isInterrupted());
 
 
        System.out.println("首次调用interrupted方法返回结果:" + Thread.currentThread().interrupted());
        System.out.println("此时中断状态:" + Thread.currentThread().isInterrupted());
        System.out.println("第二次调用interrupted方法返回结果:" + Thread.currentThread().interrupted());
        System.out.println("此时中断状态:" + Thread.currentThread().isInterrupted());
    }
}

结果:
初始中断状态:false
执行完interrupt方法后,中断状态:true
首次调用interrupted方法返回结果:true
此时中断状态:false
第二次调用interrupted方法返回结果:false
此时中断状态:false

分析:
InterruptedException异常的抛出并不是意味着线程必须得终止,它只是提醒当前线程有中断操作发生了,接下来怎么处理完全取决于线程本身,一般有3种处理方式:
1.“吞并”异常,当做什么事都没发生过。
2.继续往外抛出异常。
3.其它方式处理异常。其它处理异常的方式就有很多种了,停止当前线程或者输出异常信息等等。
在JDK1.0中,可以用stop方法来终止,但是现在这种方法已经被禁用了,改用interrupt方法。
Thread.interrupt()方法不会中断一个正在运行的线程。它的作用是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。

中断异常

public static void main(String[] args) {

    Thread thread = new Thread("thread") {
        @Override
        public void run() {
            while(true){
                try {
                    System.out.println("sleeping...");
                    Thread.sleep(2000);
                } catch (InterruptedException ex) {
                    System.out.println("thread interrupted");
                    System.out.println(this.isInterrupted());
                }
            }
        }
    };
    thread.start();
    thread.interrupt();
}

结果:
sleeping...
thread interrupted
false
sleeping...
sleeping...
sleeping...
sleeping...
sleeping...
.
.
.
分析:
thread线程启动之后进行2秒的阻塞状态,这时候main线程执行thread线程的interrupt方法,设置thread线程的状态为可中断状态,
这个时候thread就会抛出异常InterruptedException,并且在抛出异常之后擦除调thread线程的中断状态又true为false。
public static void main(String[] args) {

    Thread thread = new Thread("thread") {
        @Override
        public void run() {
            while(true){
                try {
                    System.out.println("sleeping...");
                    Thread.sleep(2000);
                } catch (InterruptedException ex) {
                    System.out.println("thread interrupted");
                    System.out.println("before:" + this.isInterrupted());
                    Thread.currentThread().interrupt();
                    System.out.println("after:" + this.isInterrupted());
                }
            }
        }
    };
    thread.start();
    thread.interrupt();
}

结果:
sleeping...
thread interrupted
before:false
after:true
sleeping...
thread interrupted
before:false
after:true
.
.
.

分析:
thread线程启动之后进行2秒的阻塞状态,这时候main线程执行thread线程的interrupt方法,设置thread线程的状态为可中断状态,
这个时候thread就会抛出异常InterruptedException,并且在抛出异常之后擦除调thread线程的中断状态又true为false,所以before的状态为false,
这个时候又执行Thread.currentThread().interrupt()再一次将thread的中断状态设置为true,由于thread的while循环,thread进行sleep又抛出中断异常,这样循环往复。

总结:

在捕获InterruptedException异常之后如果只是想记录一条日志,那么就是不负责任的做法,因为在捕获InterruptedException异常的时候会将线程的中断标志置由trrue擦除掉改为false,这样就会导致方法其他链路获取该线程的中断状态有误,不能做出正确的响应。所以至少在捕获了InterruptedException异常之后,如果你什么也不想做,那么就将标志重新置为true,以便栈中更高层的代码能知道中断,并且对中断作出响应。

 

 

 


 

C3P0:java.lang.InterruptedException: sleep interrupted

C3P0:java.lang.InterruptedException: sleep interrupted

好好的就报异常了~~

警告: com.mchange.v2.resourcepool.BasicResourcePool@8fce95 -- Thread unexpectedly interrupted while performing an acquisition attempt.
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1805)
	at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)

InterruptedException: sleep interrupted     at java.lang.Thread.sleep

InterruptedException: sleep interrupted at java.lang.Thread.sleep

 scheduler.JobScheduler: Added jobs for time 1591076608000 ms
20/06/02 13:43:28 ERROR logging.DriverLogger$DfsAsyncWriter: Failed writing driver logs to dfs
java.io.InterruptedIOException: Retry interrupted
    at org.apache.hadoop.io.retry.RetryInvocationHandler$Call.processWaitTimeAndRetryInfo(RetryInvocationHandler.java:136)
    at org.apache.hadoop.io.retry.RetryInvocationHandler$Call.invokeOnce(RetryInvocationHandler.java:107)
    at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:359)
    at com.sun.proxy.$Proxy13.getAdditionalDatanode(Unknown Source)
    at org.apache.hadoop.hdfs.DataStreamer.addDatanode2ExistingPipeline(DataStreamer.java:1362)
    at org.apache.hadoop.hdfs.DataStreamer.handleDatanodeReplacement(DataStreamer.java:1598)
    at org.apache.hadoop.hdfs.DataStreamer.setupPipelineInternal(DataStreamer.java:1499)
    at org.apache.hadoop.hdfs.DataStreamer.setupPipelineForAppendOrRecovery(DataStreamer.java:1481)
    at org.apache.hadoop.hdfs.DataStreamer.processDatanodeOrExternalError(DataStreamer.java:1256)
    at org.apache.hadoop.hdfs.DataStreamer.run(DataStreamer.java:667)
Caused by: java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at org.apache.hadoop.io.retry.RetryInvocationHandler$Call.processWaitTimeAndRetryInfo(RetryInvocationHandler.java:130)
    ... 9 more
 

java – 为什么在实现Runnable时使用Thread.currentThread().isInterrupted()而不是Thread.interrupted()?

java – 为什么在实现Runnable时使用Thread.currentThread().isInterrupted()而不是Thread.interrupted()?

在stackoverflow上,我经常看到使用Thread.currentThread().isInterrupted().当实现Runnable并在while循环中使用它时,如下所示:
public void run() {
  while(!Thread.currentThread().isInterrupted()) { ... }
}

使用Thread.interrupted()(除了使用interrupt())中断的标志被清除有什么区别吗?

我也看过Thread.currentThread().interrup().是正确的使用方法,还是Thread.interrupted()足够了?

解决方法

正如你所说的那样,区别在于,它清除线程的中断状态,而不是线程中断状态.既然你已经知道了,似乎你真正在问的是保持线程中断状态是很重要的.

首先必须确定检查中断状态(或处理InterruptedException)的代码是否被认为是线程的“所有者”.如果是这样,在某些有限的情况下,因为所有者正在实现线程的取消策略(Goetz,Java Concurrency in Practice,第143页),所以可以适当地吞下(或不抛出)InterruptedException以及中断的状态.

但在绝大多数情况下,包括一个Runnable,有关的代码不是线程所有者,也不能吞下取消状态.在这种情况下,您有两个选择:

保持线程中断状态被清除,但抛出一个InterruptedException. (这是Thread.sleep()).
>保持中断状态.

在Runnable的情况下,您不能抛出检查的异常,因为没有声明run()这样做. (反过来,我的理论是这样设计的,因为通常没有人抓住它).所以你唯一的选择是保留取消状态.

鉴于上述解释,让我回到你的直接问题.首先,如果你想检查取消状态并保留它,它更容易写

if (Thread.currentThread().isInterrupted()) doSomething;

if (Thread.interrupted()) {
    Thread.currentThread().interrupt();
    doSomething;
}

此外,如同您的原始问题一样,如果您在一个while循环中使用Thread.interrupted()作为条件,则在循环中断之后,您不知道是否终止,因为Thread.interrupted()返回true或其他一些条件已更改或一个休息声明跑了所以在这种情况下,使用Thread.currentThread().isInterrupted()真的是你唯一的选择. (当然你也可以对循环进行编码,这样才能退出的唯一原因是线程被中断了,但是你的代码会很脆弱,因为循环后你必须重新中断线程,如果别人后来并且由于某些其他原因,将代码更改为循环,否则当原始中断时,您将中断线程.)

对于您的第二个问题,正如其他人所说,不要使用Thread.currentThread().interrup(),因为它是误导的.由于interrup()是一个静态方法,在这种情况下,如果使用-Xlint编译,编译器会给您一个有用的警告:

warning: [static] static method should be qualified by type name,Thread,instead of by an expression

一些其他工具可能会做类似的工作,如Eclipse,它将显示:

The static method interrupted() from the type Thread should be accessed in a static way

今天关于为什么要捕获InterruptedException来调用Thread.currentThread.interrupt的介绍到此结束,谢谢您的阅读,有关&Thread线程:中断异常InterruptedException、C3P0:java.lang.InterruptedException: sleep interrupted、InterruptedException: sleep interrupted at java.lang.Thread.sleep、java – 为什么在实现Runnable时使用Thread.currentThread().isInterrupted()而不是Thread.interrupted()?等更多相关知识的信息可以在本站进行查询。

本文标签: