本文将介绍为什么要捕获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()?(为什么要捕获异常)
- &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()?(为什么要捕获异常)
在有效的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
方法讲解
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,而且也没有人来中断这个线程。
public static boolean interrupted();
// 检测当前线程是否已经中断,此方法会清除中断状态,也就是说,假设当前线程中断状态为true,第一次调此方法,将返回true,表明的确已经中断了,但是第二次调用后,将会返回false,因为第一次调用的操作已将中断状态重新置为false了。public boolean isInterrupted() ;
// 检测当前线程是否已经中断,此方法与上一方法的区别在于此方法不会清除中断状态。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方法。
中断异常
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
好好的就报异常了~~
警告: 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
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()?
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()?等更多相关知识的信息可以在本站进行查询。
本文标签: