Java interrupt()方法使用实例介绍

 更新时间:2023年02月03日 11:04:37   作者:愿做无知一猿  
一个线程在未正常结束之前, 被强制终止是很危险的事情. 因为它可能带来完全预料不到的严重后果比如会带着自己所持有的锁而永远的休眠,迟迟不归还锁等。 所以你看到Thread.suspend, Thread.stop等方法都被Deprecated了

前言

进入正题之前还是先回顾一个会被问无数遍的问题:

stop和interrupt的区别是什么?

简单的说就是,stop的话,那线程就真的结束了。

interrupt仅仅只是给线程标记了一下,告诉你说当前线程可以结束了,你需要自己进行结束线程。如果你自己不做处理,那这个方法调用了并看不出效果。

栗子一

不带sleep等中断抛异常方法的使用

上代码:

public class TestClassSenseOne {
    public static void main(String[] args) throws InterruptedException {
        TestThread t = new TestThread();
        //开启子线程执行
        t.start();
        //中断子线程
        t.interrupt();
        //等待子线程执行完毕,t.join() 可以这么理解,谁.join() 谁阻塞当前线程先执行自己
        t.join();
        System.out.println("主线程结束");
    }
}
class TestThread extends Thread {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            //没有被标记为中断状态就执行,上面start后直接调用中断,这句是不会输出的
            System.out.println("我没有被中断");
        }
        System.out.println("啊——————————————————————————————断了。");
    }
}

运行结果:

啊——————————————————————————————断了。
主线程结束

说明:

上面这段代码就是,interrupt()的基本用法,子线程TestThread会一直判断当前线程有没有被标记为可以中断了,直到检查到被标记了,while循环结束,子线程任务结束。

栗子二

带sleep的使用

public class TestClassSenseTwo {
    public static void main(String[] args) throws InterruptedException {
        TestThreadTwo t = new TestThreadTwo();
        //开启子线程执行
        t.start();
        //模拟真实任务,其实执行5秒就执行完了,再继续等待到20s毫无意义
        Thread.sleep(5000);
        System.out.println("模拟真实任务,其实执行5秒就执行完了,再继续等待到20s毫无意义");
        //所以在这里中断子线程
        t.interrupt();
        //等待子线程执行完毕,t.join() 可以这么理解,谁.join() 谁阻塞当前线程先执行自己
        t.join();
        System.out.println("主线程结束");
    }
}
class TestThreadTwo extends Thread {
    @Override
    public void run() {
        try {
            System.out.println("开始执行20秒的任务");
            Thread.sleep(20000);
            System.out.println("线程任务执行完毕");
        } catch (InterruptedException e) {
            System.out.println("线程在sleep的时候被中断。");
            return;
        }
    }
}

运行结果:

开始执行20秒的任务
模拟真实任务,其实执行5秒就执行完了,再继续等待到20s毫无意义
线程在sleep的时候被中断。
主线程结束

可以看到,这里了结束子线程的操作输出是在 catch块中做的,因为sleep被中断会抛出InterruptedException异常,同时也会清除当前线程被标记的 可被结束状态,如果不在catch块中结束,那么interrupt的调用并不能提前结束子线程。

大栗子

场景下使用的例子

描述:

我在程序启动时有一个检查菜单的任务,这个任务需要一直被执行,直到检查成功。

思路:

我先定义一个任务线程类,在其中while (!Thread.currentThread().isInterrupted())执行检查菜单方法,当检查菜单方法使用interrupt中断任务时说明任务完成。

上代码:

检查方法的Service接口

public interface TestService {
    void checkMenu() throws InterruptedException;
}

实现类

public class TestServiceImpl implements TestService {
    @Override
    public void checkMenu() throws InterruptedException {
        System.out.println("检查菜单----------->");
        //模拟随机成功与失败
        if (Math.random() * 10 > 4) {
            //模拟执行检查任务需要3秒耗时
            Thread.sleep(3000);
            //使用中断的方式,结束任务。
            System.out.println("检查任务完成******************,checkMenu()  使用interrupt()结束任务");
            Thread.currentThread().interrupt();
        }
    }
}

任务类

class DoMenuCheckTask extends Thread {
    @Override
    public void run() {
        TestService testService = new TestServiceImpl();
        //如果当前线程没有被中断,说明 checkMenu 没有真正成功
        while (!Thread.currentThread().isInterrupted()) {
            try {
                testService.checkMenu();
                /*
                  下面这两行的开启与关闭,便是两种结束当前任务的方式
                   1. 这里不使用sleep ,任务正常被 interrupt 结束
                   2. 这里使用 sleep, interrupt打断的就是 sleep(),打断sleep会清除isInterrupted中断状态,
                        并抛出 java.lang.InterruptedException: sleep interrupted 异常,所以,不在catch块中结束任务,
                        任务便无法结束了。
                 */
//                System.out.println("菜单检查没有通过中断完成任务,休眠5秒后继续执行----------");
//                //如果这里使用了 sleep 那么任务便是通过下面catch块中结束。
//                Thread.sleep(5000);
            } catch (InterruptedException e) {
                //被中断,任务结束
                e.printStackTrace();
                System.out.println("菜单检查通过中断interrupt成功完成----------->>>>>>>>");
                return;
            }
        }
    }
}

执行

public class SceneExample {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("主线程开始执行----------->>>>>>>>");
        DoMenuCheckTask task = new DoMenuCheckTask();
        //开始菜单检查执行任务
        task.start();
        //让检查任务先执行
        task.join();
        System.out.println("主线程结束执行----------->>>>>>>>");
    }
}

不使用sleep输出结果:

主线程开始执行----------->>>>>>>>
检查菜单----------->
检查任务完成******************,checkMenu()  使用interrupt()结束任务
主线程结束执行----------->>>>>>>>

Process finished with exit code 0

使用sleep的输出结果:

主线程开始执行----------->>>>>>>>
检查菜单----------->
检查任务完成******************,checkMenu()  使用interrupt()结束任务
菜单检查没有通过中断完成任务,休眠5秒后继续执行----------
菜单检查通过中断interrupt成功完成----------->>>>>>>>
主线程结束执行----------->>>>>>>>
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.kusch.demo.test.example.DoMenuCheckTask.run(SceneExample.java:47)

Process finished with exit code 0

到此这篇关于Java interrupt()方法使用实例介绍的文章就介绍到这了,更多相关Java interrupt()内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于@RequestParam与@RequestBody使用对比

    基于@RequestParam与@RequestBody使用对比

    这篇文章主要介绍了@RequestParam与@RequestBody的使用对比,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Java IO流之原理分类与节点流文件操作详解

    Java IO流之原理分类与节点流文件操作详解

    流(Stream)是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道,数据源发送的数据经过这个通道到达目的地,按流向区分为输入流和输出流
    2021-10-10
  • mybatis-plus雪花算法生成Id使用详解

    mybatis-plus雪花算法生成Id使用详解

    本文主要介绍了mybatis-plus雪花算法生成Id使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • java 获取已知文件扩展名的代码

    java 获取已知文件扩展名的代码

    java 编写程序获取已知文件的扩展名. 注意: abc.txt的扩展名是txt, abc.java.txt的扩展名也是txt.,需要的朋友可以参考下
    2017-02-02
  • 基于java开发之系统托盘的应用

    基于java开发之系统托盘的应用

    本篇文章介绍了,基于java开发之系统托盘的应用。需要的朋友参考下
    2013-05-05
  • IDEA报错:无效的源发行版解决方案

    IDEA报错:无效的源发行版解决方案

    很多小伙伴在刷新maven的时候总会报 Error:java:无效的源发行版,下面这篇文章主要给大家介绍了关于IDEA报错:无效的源发行版的解决方案,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • JAVA最容易忽视的数据类型之枚举详解

    JAVA最容易忽视的数据类型之枚举详解

    这篇文章主要给大家介绍了关于JAVA最容易忽视的数据类型之枚举的相关资料,Java中的枚举类型是一种特殊的类型,它允许程序员定义一个固定的值集合,并为每个值分配一个名称,枚举类型提供了一种简单、安全和可读性强的方式来表示一组相关的常量,需要的朋友可以参考下
    2023-10-10
  • JPA使用乐观锁应对高并发方式

    JPA使用乐观锁应对高并发方式

    这篇文章主要介绍了JPA使用乐观锁应对高并发方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Java文件拒绝访问问题及解决

    Java文件拒绝访问问题及解决

    这篇文章主要介绍了Java文件拒绝访问问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • springboot 自定义异常并捕获异常返给前端的实现代码

    springboot 自定义异常并捕获异常返给前端的实现代码

    在开发中,如果用try catch的方式,每个方法都需要单独实现,为了方便分类异常,返回给前端,采用了@ControllerAdvice注解和继承了RuntimeException的方式来实现,具体实现内容跟随小编一起看看吧
    2021-11-11

最新评论