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异常的常用方法:
class BlockQueueTest {
ArrayBlockingQueue testQueue = new ArrayBlockingQueue(4);
public int poll() throws InterruptedException {
return testQueue.poll(10, TimeUnit.SECONDS);
}
public void put() throws InterruptedException {
testQueue.put(1);
}
}
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();
}
}
}
}
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/