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
猜你喜欢
- 在做相机开发时,遇到一个问题,就是需要监听屏幕旋转。最简单的就是使用onConfigurationChanged()和Orientation
- 做tcp网络编程,要解析一批批的数据,可是数据是通过Socket连接的InputStream一次次读取的,读取到的不是需要转换的对象,而是要
- 《Android开发艺术探索》笔记:在Activity的onCreate()或者onResume()中去获得View的高度的时候不能正确获得
- 本文实例讲述了Android开发之文件操作。分享给大家供大家参考,具体如下:目前,几乎所有的设备都会涉及到文件的操作,例如什么电脑,手机等设
- 最近学了很多的知识,脑容量小,记不清,还是得做做练习!今天就做了一个扑克牌的练习首先呢..这个逻辑一定要非常清楚,我们要想做出一副扑克牌,必
- 本文实例为大家分享了Unity3D实现旋钮控制灯光效果的具体代码,供大家参考,具体内容如下前言实际上使用的是非常简单的方式,通过开启以及关闭
- 日常对于金额计算,应该都是用的BigDecimal,可是苦于没有好的工具类方法,现在贡献一个我正在用的对于数字计算的工具类,项目中就是用的这
- 获取map的key和value的方法分为两种形式:map.keySet():先获取map的key,然后根据key获取对应的value;map
- 一、为什么要有泛型?我们在写一些方法时可能会方法名相同,参数类型不同的方法,这种叫做重载。如果只是因为参数类型不同里面做的业务逻辑都是相同的
- 1、修改全局配置文件(application.yml)server: port: 9001 servlet: &nb
- 最近在一本J2EE的书中看到了很不错的对集合框架的说明文章,筛选后发上来和大家共享,集合框架提供管理对象集合的接口和类.它包含接口,类,算法
- 本文实例为大家分享了Android Scroller实现弹性滑动的具体代码,供大家参考,具体内容如下首先看下实现效果,可以看到当我们手指松开
- 本文以实例描述了C#实现让窗体永远在窗体最前面显示的方法,具体步骤如下:1、新建一个窗体程序,添加一个Timer以及设置它可用并绑定事件。2
- 一致性哈希节点的增加和减少,大部分节点的 Hash一致package consistenthashimport ("hash/cr
- 1.c#里面的TabControl控件没有关闭按钮,而且很难看。2.有一些已经做好的第三方控件,但是收费。3.由于我的故障树推理诊断项目在绘
- 看到篇帖子, 国外一个技术面试官在面试senior java developer的时候, 问到一个weak reference相关的问题.
- 一、概述在软件开发中,有些对象由于创建成本高、访问时需要与其它进程交互等原因,直接访问会造成系统速度慢、复杂度增大等问题。这时可以使用代理模
- 我们知道Eclipse创建的工程默认是有个assets文件夹的,但是Android studio默认没有帮我们创建,那么我们就自己创建一个就
- 上一篇中说到了 Expression 的一些概念性东西,其实也是为了这一篇做知识准备。为了实现 EFCore 的多条件、连表查询,简化查询代
- Android ListView的优化,在做Android项目的时候,在用到ListView 界面及数据显示,这个时候如果资源过大,对项目来