1.线程可能在执行过程中阻塞或者暂停执行,例如等待IO结束,等待获得一个锁,等待从Thread.sleep方法中醒来,或者等待另一个线程的计算结果。
2.阻塞方法:BlockingQueue的put和take方法会抛出收检查异常:InterruptedException。还有类似的方法如Thread.sleep。抛出InterruptedException的方法叫做阻塞方法。如果这个方法被中断,他将努力提前结束阻塞状态。
3.中断是一种协作机制,一个线程不能强制要求其他线程停止正在执行的操作而去执行其他操作。当线程A中断线程B时,A只是要求B在执行到某个可以暂停的地方停止正在执行的操作。但是实际怎样处理中断是由线程B自己决定的。所以在,类中调用阻塞方法时,需要添加中断处理。
4.什么时候会发生中断:
- 点击某个桌面应用中的取消按钮时;
- 某个操作超过了一定的执行时间限制需要中止时;
- 多个线程做相同的事情,只要一个线程成功其它线程都可以取消时;
- 一组线程中的一个或多个出现错误导致整组都无法继续时;
- 当一个应用或服务需要停止时。
我们在使用电脑过程中都会发现,当我们点击取消按钮的时候,大多数情况下并不是立刻结束,而是会提示正在取消并且会持续一段时间,这个就是在进行中断处理。
4.什么时候可以中断:只有阻塞方法才可以中断,因为它提供了中断响应的策略。中断后不会产生问题。但是在非中断方法中,比如线程在执行一个排序算法,那么在排序过程中并不会发生中断,因为此时中断会产生问题即排序的数组中一部分有序一部分无序。此时如果在排序排序过程中必须处理才能中断。此时如果要强制结束线程必须调用Thread.stop()或者Thread.destroy(),但是这样强制结束线程是不安全的。
例如下面的例子:当线程中断时,还是会继续输出2和3.
public class InterruptedExample implements Runnable {
@Override
public void run() {
System.out.println("1");
Thread.currentThread().interrupt();
System.out.println("2");
System.out.println("3");
}
public static void main(String[] args) {
Thread interruptedThread = new Thread(new InterruptedExample());
interruptedThread.start();
}
}
5.中断处理策略:
- 传递InterruptedException:将中断处理交给方法的调用者,包括根本不捕获异常或者捕获异常后进行简单的处理之后再抛出异常。
- 恢复中断:有时候不能抛出InterruptedException,例如在Runnable中,这时需要捕获异常并且恢复异常。
- 屏蔽中断:中断发生后捕获异常但是什么都不做。
6.中断方法
- public void interrupt():中断线程
- public static boolean interrupted():查询当前线程中断状态,如果已经中断,就清除中断。
- public boolean isInterrupted():查询当前线程中断状态,但是不会改变中断状态。
7.当线程正在调用阻塞方法的过程中发生中断,阻塞方法停止并且会抛出InterruptedException异常。如果捕捉到异常但不进行处理,那么线程会继续执行。
public class InterruptedExample implements Runnable {
@Override
public void run() {
System.out.println("before interrupt");
//阻塞10秒
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("interrupted happen");
//return;
}
//捕捉到异常后,线程状态变为没有中断
System.out.println("isInterrupted:" + Thread.currentThread().isInterrupted());
System.out.println("after interrupted");
}
public static void main(String[] args) throws InterruptedException {
Thread interruptedThread = new Thread(new InterruptedExample());
interruptedThread.start();
Thread.sleep(200);
System.out.println("after sleep");
interruptedThread.interrupt();
}
}
result:
before interrupt
after sleep
interrupted happen
isInterrupted:false
after interrupted
例子中捕获到异常之后并没有向上层抛出或者返回,还会继续执行下面的程序。所以这个异常处理是不合理的。应该在异常处理之后return或者恢复中断或者向上层抛出异常(run方法不能向上抛出)。