Interrupt方法详解
1.简介
interrupt方法是Thread类中的一个普通方法,它的作用主要是通知中断当前线程。
- 当线程处于wait、sleep、join方法阻塞时被中断,则会清除标记状态,并抛出InterruptedException异常
- 当线程处于正常执行程序时,只会设置标记状态
接下来我们以案例来详细说明interrupt方法以及相关方法的使用。
2.interrupt不起作用的情况
inturrept方法通过设置一个标记状态为true,是否中断线程交由线程内部去处理。如果线程内部不针对这个标记状态做处理,线程是不会中断的,如下图所示。
代码
线程方法:
@Slf4j
class MonitorThread1 {
private Thread monitorThread;
public void start(){
monitorThread = new Thread(()->{
while(true){
log.info("监视线程.......");
}
},"monitor-thread");
monitorThread.start();
}
public void stop(){
monitorThread.interrupt();
}
}
测试主类:
public static void main(String[] args) throws InterruptedException {
MonitorThread1 monitorThread = new MonitorThread1();
monitorThread.start();
Thread.sleep(3500);
monitorThread.stop();
}
运行结果:
线程会一直运行下,并不会被中断。
3.interrupt方法结合isInterrupted使用
isInterrupted方法是Thread类中的普通方法,作用是返回当前线程的中断标记。
有了这个方法,那我们应该就可以理解了,interrupt方法结合isInterrupted使用就可以中断某个线程了。
代码
线程方法:
@Slf4j
class MonitorThread2 {
private Thread monitorThread;
public void start(){
monitorThread = new Thread(()->{
while(true){
if (Thread.currentThread().isInterrupted()) {
log.info("中断标记为true了,该退出了,退出前可以做一些收尾工作......");
break;
}
log.info("监视线程.......");
}
},"monitor-thread");
monitorThread.start();
}
public void stop(){
monitorThread.interrupt();
}
}
测试主类:
public static void main(String[] args) throws InterruptedException {
MonitorThread2 monitorThread = new MonitorThread2();
monitorThread.start();
Thread.sleep(5);
monitorThread.stop();
}
输出结果:
4.interrupt方法结合isInterrupted方法中断sleep方法
这个案例主要用来说明interrupt方法在中断sleep、wait、join方法时会重置中断标记,并抛出InterruptedException异常。
代码
线程方法:
@Slf4j
class MonitorThread{
private Thread monitorThread;
public void start(){
monitorThread = new Thread(()->{
while(true){
Thread thread = Thread.currentThread();
if(thread.isInterrupted()){
log.info("中断标记为true了,该退出了,退出前可以做一些收尾工作......");
break;
}
try {
//如果在sleep时触发打断标记,异常被捕获并且清除打断标记
Thread.sleep(1000);
//如果是这里被打断了,不会进异常
log.info("监视线程......");
} catch (InterruptedException e) {
//打印一下中断标记状态
System.out.println(thread.isInterrupted());
log.error("",e);
}
}
},"monitor-thread");
monitorThread.start();
}
public void stop(){
monitorThread.interrupt();
}
}
测试主类:
public static void main(String[] args) throws InterruptedException {
MonitorThread monitorThread = new MonitorThread();
monitorThread.start();
Thread.sleep(3500);
monitorThread.stop();
}
输出结果:
- 可以看到异常被捕获后,中断标记为false,表示sleep方法处中断时确实清除了中断标记,程序会继续运行
那如果不想让程序继续运行,需要在catch块中再调用一次interrupt方法,让其重新设置中断标记为true。改一下线程方法如下:
总结
案例中使用interrupt方法结合isInterrupted方法做到中断线程。除了isInterrupted方法外,还有interrupted方法也可以和interrupt方法结合使用。
isInterrupted方法和interrupted方法的区别:
-
相同点
- 两者方法调用后都是返回当前线程的中断标记位
-
不同点
- isInterrupted是Thread类的普通方法,interrupted是Thread类的静态方法
- isInterrupted方法返回当前中断标记位后对标记位不再做处理,interrupted方法返回标记位后会将标记位重新置为false