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

作者:愿做无知一猿 时间:2022-05-04 11:09:35 

前言

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

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

来源:https://blog.csdn.net/qq_38397501/article/details/126181191

标签:Java,interrupt
0
投稿

猜你喜欢

  • spring cloud整合ribbon问题及解决方案

    2023-07-25 04:24:49
  • C#多线程系列之任务基础(三)

    2023-10-08 13:43:34
  • 从Python程序中访问Java类的简单示例

    2022-02-19 08:53:13
  • 在eclipse中中文汉字乱码的解决方案

    2023-11-25 10:13:27
  • 详解Java的Spring框架中的事务管理方式

    2022-02-03 13:57:47
  • Android自定义控件案例汇总1(菜单、popupwindow、viewpager)

    2021-11-22 14:37:32
  • Spring Boot下的Job定时任务

    2021-10-23 05:16:14
  • Spring AOP实现记录操作日志

    2022-06-04 06:03:53
  • Java如何把int类型转换成byte

    2023-03-13 11:12:39
  • Android itemDecoration接口实现吸顶悬浮标题

    2023-03-14 00:58:31
  • 详解jeefast和Mybatis实现二级联动的问题

    2022-11-10 05:10:15
  • 在Eclipse安装Spring boot插件的步骤(图文)

    2023-01-14 05:04:05
  • EasyExcel实现导入+各种数据校验功能

    2022-05-12 13:05:26
  • C#使用NPOI设置Excel下拉选项

    2022-11-28 07:05:39
  • Java 创建PDF打印小册子案例

    2023-01-17 04:19:40
  • C#利用iTextSharp组件给PDF文档添加图片/文字水印

    2021-11-03 20:18:31
  • C#多线程异步执行和跨线程访问控件Helper

    2022-02-09 12:24:32
  • Java多线程编程之访问共享对象和数据的方法

    2022-10-01 07:05:02
  • Android线程实现图片轮播

    2021-06-02 17:49:23
  • Java中四种访问权限资料整理

    2021-12-04 13:23:58
  • asp之家 软件编程 m.aspxhome.com