1.为什么使用中断机制
在多线程的场景中,有的线程可能迷失在怪圈无法自拔,或者执行一个超长的任务,这个时候如果别人不通知则就停不下来,别人(其他线程)也一直等待干不了活, 造成资源的浪费,这时就可以用其他线程在恰当的时机给它个中断通知,被“中断”的线程可以选择在恰当的时机选择跳出怪圈,最大化的利用CPU资源.Java没有提供一种安全直接的方法来停止某个线程,但是Java提供了中断机制。
2.Java 中断机制
如果任何线程处于睡眠或等待状态(即调用 sleep() 或 wait()),则调用该线程上的 interrupt() 方法,会中断睡眠或等待状态并抛出 InterruptedException。 如果线程未处于休眠或等待状态,则调用 interrupt() 方法会执行正常行为,并且不会中断线程,但会将中断标志设置为 true。 我们先来看看Thread类提供的线程中断方法。中断可以理解为线程的一个标识位属性,它表示一个运行中的线程是否被其他线程进行 了中断操作。中断好比其他线程对该线程打了个招呼,其他线程通过调用该线程的interrupt() 方法对其进行中断操作。 线程通过检查自身是否被中断来进行响应,线程通过方法isInterrupted()来进行判断是否 被中断,也可以调用静态方法Thread.interrupted()对当前线程的中断标识位进行复位。如果该 线程已经处于终结状态,即使该线程被中断过,在调用该线程对象的isInterrupted()时依旧会返 回false。
3.什么是打断异常
当一个线程在等待、睡眠或以其他方式被占用时被中断,就会抛出一个 InterruptedException。 换句话说,一些代码在我们的线程上调用了interrupt() 方法。 它是一个受检异常,Java 中的许多阻塞操作都可以抛出它。
3.1线程中断方法
public void interrupt() { ... }//线程调用打断方法
public boolean isInterrupted() { ... }//判断中断标志位, 线程的中断状态不受此方法的影响
public static boolean interrupted() { ... }//与interrupted类似,线程的中断状态会被清理
3.2中断标志位
中断机制是使用称为中断状态的标志来实现的。 每个线程都有一个代表其中断状态的布尔属性。 调用 Thread.interrupt() 设置此标志。 当线程通过调用静态方法 Thread.interrupted() 检查中断时,中断状态被清除。 为了响应中断请求,我们必须处理 InterruptedException。
4.中断例子
4.1 捕获打断异常
public void testInterruptExeception(){
Thread thread = new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().isInterrupted());
throw new RuntimeException("Thread interrupted..."+e);
}
});
thread.start();
thread.interrupt();
}
//outputs
false //没有相应中断,打断状态被清理
Exception in thread "Thread-0" java.lang.RuntimeException: Thread interrupted...java.lang.InterruptedException: sleep interrupted
4.2 捕获异常后程序继续运行
public void testInterruptExeception2(){
Thread thread = new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("线程被打断 "+e);
}
System.out.println("线程继续运行。。。 ");
});
thread.start();
thread.interrupt();
}
//output
线程被打断 java.lang.InterruptedException: sleep interrupted
线程继续运行。。。
4.3.线程没有在等待或睡眠状态,设置打断状态
public void testInterruptExeception3(){
Thread thread = new Thread(()->{
for(int i=1;i<=5;i++){
System.out.println(i);
}
System.out.println("thread interrupt state:"+ Thread.currentThread().isInterrupted());
});
thread.start();
thread.interrupt();
}
//output
1
2
3
4
5
thread interrupt state:true
4.4响应中断,如果不响应中断,下面的程序会一直执行
public void testInterruptExeception4() throws InterruptedException {
Thread thread = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()){
System.out.println("任务停止,结束退出!");
return;
}
else
System.out.println("线程运行中。。。");
}
});
thread.start();
Thread.sleep(100);
thread.interrupt();
}
//output
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
.
.
.
任务停止,结束退出!
5.总结
在上面的例子中,我们讨论了如何处理中断异常,如何使线程处于中断状态,以及应该如何响应中断, 如果我们处理得当,我们可以平衡应用程序的响应性和健壮性。
分享到: