Java多线程中停止线程遇到线程阻塞的处理方法详解

 更新时间:2023年10月26日 11:02:43   作者:java持续实践  
这篇文章主要介绍了Java多线程中停止线程遇到线程阻塞的处理方法详解,在阻塞状态下,线程会释放CPU资源,从而允许其他线程执行,线程阻塞是实现多线程编程中重要的概念,可以提高程序的效率和资源利用率,需要的朋友可以参考下

Java多线程中停止线程遇到线程阻塞的处理方法详解

线程可能被阻塞

子线程sleep的过程中, 给出中断信号的demo

当子线程正在休眠的过程中, 去进行线程的中断. 因此主线程要等子线程执行到 Thread.sleep(1000);这一行代码,因此在main线程中, 给出了Thread.sleep(500);

public class RightWayStopThreadWithSleep {


    public static void main(String[] args) throws InterruptedException {

        // 创建线程任务
        Runnable runnable = () -> {
            int num = 0;
            try {
                while (num <= 300 && !Thread.currentThread().isInterrupted()) {
                    if (num % 100 == 0) {
                        System.out.println(num + " 是100的整数");
                    }
                    num++;
                }

                //执行完成循环累加后, 执行sleep, 此时主线程给出中断信号
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        };

        //启动线程
        Thread thread = new Thread(runnable);

        thread.start();

        //当子线程 正在休眠的过程中, 去进行线程的中断.
        //因此要等子线程执行到  Thread.sleep(1000);这一行代码
        //此处的  Thread.sleep(500); 是给子线程  循环0到300的时间用的
        Thread.sleep(500);

        //子线程执行完成0到300累加后, 在子线程sleep的过程中, 去给出中断的信号
        thread.interrupt();
    }
}

程序执行的结果如下 :

可以看到 当子线程执行完循环的任务后 ,响应主线程的中断信号的方式为 抛出异常. 那是因为在子线程中, sleep方法被try catch所包裹了, 面对在sleep中,这种类似的阻塞操作的时候, 就会catch出这个异常, 打印如下的异常 ,响应中断 java.lang.InterruptedException: sleep interrupted 通过断点调试可以看到, 进入了catch的代码块.

而如果子线程没有阻塞的状态, 那么子线程即使收到了中断的信号, 也不会抛出异常.

如果线程在每次迭代时都阻塞

线程在每次迭代时都阻塞的代码如下. 在子线程循环的过程中, 每次都Thread.sleep(10); 休眠10ms. 在子线程运行5s,后, 主线程给子线程发出中断的通知.

public class RightWayStopThreadWithSleepEveryLoop {

    public static void main(String[] args) throws InterruptedException {

        // 创建线程任务
        Runnable runnable = () -> {
            int num = 0;
            try {
                while (num <= 10000 && !Thread.currentThread().isInterrupted()) {
                    if (num % 100 == 0) {
                        System.out.println(num + " 是100的整数");
                    }
                    num++;
                    //每一次循环,休眠10ms
                    Thread.sleep(10);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        //启动线程
        Thread thread = new Thread(runnable);
        thread.start();

        //此处的  Thread.sleep(5000); 是休眠主线程, 让子线程运行5s,
        //子线程运行5s后, 给出子线程的休眠信号
        Thread.sleep(5000);
        thread.interrupt();
    }
}

此时打印如下. 子线程打印出来sleep过程中被中断的异常

与上一节线程可能被阻塞的区别是, 此时由于每一次的循环,都会sleep, 因此真正判断子线程是否被中断, 不是使用Thread.currentThread().isInterrupted(), 而是在Thread.sleep(10); 休眠的过程中, 就能立刻的感知到了中断通知, 就会抛出异常. 因此可以把代码修改如下, 在子线程的while (num <= 10000) 时, 就不需要进行判断线程是否中断了.

public class RightWayStopThreadWithSleepEveryLoop {


    public static void main(String[] args) throws InterruptedException {

        // 创建线程任务
        Runnable runnable = () -> {
            int num = 0;
            try {
                while (num <= 10000) {
                    if (num % 100 == 0) {
                        System.out.println(num + " 是100的整数");
                    }
                    num++;
                    //每一次循环,休眠10ms
                    Thread.sleep(10);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        //启动线程
        Thread thread = new Thread(runnable);
        thread.start();

        //此处的  Thread.sleep(5000); 是休眠主线程, 让子线程运行5s,
        //子线程运行5s后, 给出子线程的休眠信号
        Thread.sleep(5000);
        thread.interrupt();
    }

}

打印的结果如下. 与加上判断线程是否中断的一致.

因此, 只要子线程在while循环的过程中, 每一次循环都会有让线程进行阻塞一段时间的情况下, 就不需要加上线程是否被中断的条件判断 . 因为会在阻塞的过程中,检测中断的状态, 并且抛出异常

到此这篇关于Java多线程中停止线程遇到线程阻塞的处理方法详解的文章就介绍到这了,更多相关Java线程阻塞的处理方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于Java错误提示之找不到或无法加载主类的问题及正确处理方法

    关于Java错误提示之找不到或无法加载主类的问题及正确处理方法

    当我们在初学Java的是时候,类文件中是不设定包名(package)的,这种情况下注意classpath,基本上没有问题, 本文主要说明classpath和系统环境变量PATH都没问题的情况下出错原因和正确处理方法,感兴趣的朋友一起看看吧
    2022-01-01
  • mybatis-plus 表名添加前缀的实现方法

    mybatis-plus 表名添加前缀的实现方法

    这篇文章主要介绍了mybatis-plus 表名添加前缀的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Java手动创建线程池代码实例

    Java手动创建线程池代码实例

    这篇文章主要介绍了Java手动创建线程池代码实例,FixedThreadPool或者SingleThreadPool,允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM,需要的朋友可以参考下
    2023-12-12
  • 给Java文件打成独立JAR包的详细步骤记录

    给Java文件打成独立JAR包的详细步骤记录

    这篇文章主要介绍了给Java文件打成独立JAR包的相关资料,文中将Java文件打包成独立的JAR包,包括非Maven和Maven项目的打包步骤,需要的朋友可以参考下
    2024-12-12
  • java内存占用高案例

    java内存占用高案例

    本文主要介绍了java内存占用高案例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-08-08
  • Java Stream比较两个List的差异并取出不同的对象四种方法

    Java Stream比较两个List的差异并取出不同的对象四种方法

    今天开发一个需求时要对A和B两个List集合遍历,并比较出集合A有,而集合B没有的值,下面这篇文章主要给大家介绍了关于Java Stream比较两个List的差异并取出不同对象的四种方法,需要的朋友可以参考下
    2024-01-01
  • Java 中Object的wait() notify() notifyAll()方法使用

    Java 中Object的wait() notify() notifyAll()方法使用

    这篇文章主要介绍了Java 中Object的wait() notify() notifyAll()方法使用的相关资料,需要的朋友可以参考下
    2017-05-05
  • Java LongAdder原理解析与实战应用小结

    Java LongAdder原理解析与实战应用小结

    LongAdder是Java 8中java.util.concurrent.atomic包引入的高性能计数器类,专为高并发场景下的数值累加操作优化设计,本文给大家介绍Java LongAdder原理解析与实战应用小结,感兴趣的朋友一起看看吧
    2025-06-06
  • JAVA进阶篇之详细了解File文件的常用API

    JAVA进阶篇之详细了解File文件的常用API

    这篇文章主要给大家介绍了关于JAVA进阶篇之详细了解File文件的常用API的相关资料,File用于表示文件系统中的一个文件或目录,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • SpringBoot如何实现接口版本控制

    SpringBoot如何实现接口版本控制

    这篇文章主要介绍了SpringBoot如何实现接口版本控制,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10

最新评论