首页 > 其他分享 >一文彻底搞懂线程中断interrupt导致sleep报InterruptException

一文彻底搞懂线程中断interrupt导致sleep报InterruptException

时间:2024-11-16 09:17:55浏览次数:3  
标签:Thread 中断 InterruptedException 线程 InterruptException interrupt sleep 搞懂

目录

一文彻底搞懂线程中断interrupt导致sleep报InterruptException

问题再现

以下这个场景:

public class ThreadDemo13 {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(()->{

            while(!Thread.currentThread().isInterrupted()){
                System.out.println("线程");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        Thread.sleep(3000);
        System.out.println("让线程结束");
        t.interrupt();
    }
}

在这里插入图片描述

代码执行到这里,可以看到,代码中出现了一个异常,t线程并没有真的结束!!!

刚才这里的interrupt导致sleep出现异常!!

问题分析

为什么??

我们来理一下思路:t.start()创建了一个新线程,让主线程休眠3秒,为了让线程执行一会,然后主线程想让这个线程结束,就用了interrupt方法。但是结果告诉我们,它只是报了InterruptedException,并且没有结束,而是继续执行了下去。

我们能明确的是:主线程调用interrupt之后,会触发InterruptedException异常。但是程序继续执行了下去==,说明while循环的条件没有被破坏,说明 !Thread.currentThread().isInterrupted() 是true,那就说明 Thread.currentThread().isInterrupted() 是false,说明中断标志位被清除了!!!!!==

原来,在触发InterruptException异常的同时,JVM会同时把线程的中断标志位清除,所以,这个时候在run()方法中判断的 Thread.currentThread().isInterrupted()会返回false,也就不会退出当前while循环了。

问题解决

正确的处理方式应该是在ThreadDemo13类中方法中的while(true)循环中捕获异常之后重新设置中断标志位或者break退出,所以,正确的ThreadDemo13类的代码如下所示。

public class ThreadDemo13 {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(()->{

            while(!Thread.currentThread().isInterrupted()){
                System.out.println("线程");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                   break;
                }
            }
        });
        t.start();
        Thread.sleep(3000);
        System.out.println("让线程结束");
        t.interrupt();
    }
}

在这里插入图片描述

这样程序就能正常结束

总结

处理InterruptedException异常时要小心,如果在调用执行线程的interrupt()方法中断执行线程时,抛出了InterruptedException异常,则在触发InterruptedException异常的同时,JVM会同时把执行线程的中断标志位清除,此时调用执行线程的isInterrupted()方法时,会返回false。此时,正确的处理方式是在执行线程的run()方法中捕获到InterruptedException异常,并重新设置中断标志位(也就是在捕获InterruptedException异常的catch代码块中,重新调用当前线程的interrupt()方法)或者直接中断。

如果没有sLeep, interrupt可以让线程顺利结束。

有了sLeep引起了变数!

在执行sLeep的过程中,调用Interrupt,大概率sLeep休眠时间还没到,被提前唤醒了。

提前唤醒,会做两件事:

1.抛出InterruptedException(紧接着就会被catch获取到)

2.清除Thread对象的isInterrupt标志位。

通过Interrupt方法,已经把标志位设为true了,但是sLeep提前唤醒操作,就把标志位又设回false。(此时循环还是会继续执行了)

要想让线程结束,只需要在catch中加上break就行了。

不只是sLeep会清除异常,很多方法都会!!!

标签:Thread,中断,InterruptedException,线程,InterruptException,interrupt,sleep,搞懂
From: https://blog.csdn.net/t1750982356/article/details/143811856

相关文章

  • 多线程的入门与理解
    文章目录一、认识多线程1.1概念(1)线程是什么(2)为什么要有线程(3)进程和线程的区别(4)java的线程与操作系统线程的关系1.2第一个多线程程序1.3创建线程方法一继承Thread类方法二实现Runnable接口其他变形1.4多线程的优势二、Thread类及常见方法2.1Thread的常见构造方法2.2......
  • Linux编程:基于 Unix Domain Socket 的进程/线程间通信实时性优化
    文章目录0.引言1.使用`epoll`边缘触发模式非不要不选择阻塞模式边缘触发(ET)模式优点示例2.使用实时调度策略3.CPU绑定4.使用无锁缓冲区5.优化消息传递的大小和频率6.使用`SO_RCVTIMEO`和`SO_SNDTIMEO`7.示例代码其他阅读0.引言前几天被问到“如何优......
  • 32. 线程、进程与协程
    一、什么是多任务  如果一个操作系统上同时运行了多个程序,那么称这个操作系统就是多任务的操作系统,例如:Windows、Mac、Android、IOS、Harmony等。如果是一个程序,它可以同时执行多个事情,那么就称为多任务的程序。  一个CPU默认可以执行一个程序,如果想要多个程序一起执行......
  • 线程间通信
    使用锁+信号量+队列,可以实现线程间通信。 下面是一个生产者,消费者的例子。 #include<iostream>#include<queue>#include<thread>#include<mutex>#include<condition_variable>#include<chrono>//定义一个消息类型structMessage{intdata;};......
  • 多线程篇·线程相关知识
    一、线程状态线程是cpu任务调度的最小执行单位,每个线程拥有自己独立的程序计数器、虚拟机栈、本地方法栈。线程状态包括:创建、就绪、运行、阻塞、死亡。二、线程状态切换三、阻塞唤醒过程阻塞以下三个方法的调用都会使当前线程阻塞,该线程将会被放置到对该Object的请......
  • 多线程篇·线程相关知识
    一、线程状态线程是cpu任务调度的最小执行单位,每个线程拥有自己独立的程序计数器、虚拟机栈、本地方法栈。线程状态包括:创建、就绪、运行、阻塞、死亡。二、线程状态切换三、阻塞唤醒过程阻塞以下三个方法的调用都会使当前线程阻塞,该线程将会被放置到对该Object的请......
  • 线程状态切换
    Java线程控制方法的作用及其区别:start:作用:启动线程,由虚拟机自动调度执行run()方法。区别:线程处于就绪状态。run:作用:线程逻辑代码块处理,JVM调度执行。区别:线程处于运行状态。sleep:作用:让当前正在执行的线程休眠(暂停执行)。区别:不释放锁。wait:......
  • 线程状态切换
    Java线程控制方法的作用及其区别:start:作用:启动线程,由虚拟机自动调度执行run()方法。区别:线程处于就绪状态。run:作用:线程逻辑代码块处理,JVM调度执行。区别:线程处于运行状态。sleep:作用:让当前正在执行的线程休眠(暂停执行)。区别:不释放锁。wait:......
  • 实战指南:理解 ThreadLocal 原理并用于Java 多线程上下文管理
    目录一、ThreadLocal基本知识回顾分析(一)ThreadLocal原理(二)既然ThreadLocalMap的key是弱引用,GC之后key是否为null?(三)ThreadLocal中的内存泄漏问题及JDK处理方法(四)部分核心源码回顾ThreadLocal.set()方法源码详解ThreadLocalMap.get()方法详解ThreadLocal.remove()方法源......
  • python多线程和网络编程
    一、多线程1.进程、线程和并行执行学习目标:了解什么是进程、线程,了解什么是并行执行进程比作公司,线程比作员工,多线程并行执行就比作公司的不同员工在同一时间去做不同的事。总结2.多线程编程学习目标:掌握使用threading模块完成多线程编程当你想实现唱歌和跳舞一......