0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用stop、suspend方法来中断线程的坏处在哪?

Android编程精选 来源:CSDN技术社区 作者:浪舟子 2021-07-26 14:23 次阅读

我们知道像stop、suspend这几种中断或者阻塞线程的方法在较高java版本中已经被标记上了@Deprecated过期标签,那么为什么她们曾经登上了java的历史舞台而又渐渐的推出了舞台呢,到底是人性的扭曲还是道德的沦丧呢,亦或是她们不思进取被取而代之呢,如果是被取而代之,那么取而代之的又是何方人也,本文我们将一探究竟。

一、stop的落幕首先stop方法的作用是什么呢,用java源码中的一句注释来了解一下:Forces the thread to stop executing.,即强制线程停止执行,‘Forces’似乎已经透漏出了stop方法的蛮狠无理。那么我们再看看java开发者是怎们解释stop被淘汰了的。

我们从中可以看出以下几点:

stop这种方法本质上是不安全的

使用Thread.stop停止线程会导致它解锁所有已锁定的监视器,即直接释放当前线程已经获取到的所有锁,使得当前线程直接进入阻塞状态

我们举例来看一下上边提到的两点:

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

Object o1=new Object();

Object o2=new Object();

Thread t1=new Thread(()-》{

synchronized (o1)

{

synchronized (o2)

{

try {

System.out.println(“t1获取到锁”);

Thread.sleep(5000);

System.out.println(“t1结束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

t1.start();

Thread.sleep(1000);

Thread t2=new Thread(()-》{

synchronized (o1)

{

synchronized (o2)

{

try {

System.out.println(“t2获取到锁”);

Thread.sleep(5000);

System.out.println(“t2结束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

});

t2.start();

t1.stop();

}

运行结果:

1fb0958c-e009-11eb-9e57-12bb97331649.png

可以看到,当线程t1在获取到o1和o2两个锁开始执行,在还没有执行结束的时候,主线程调用了t1的stop方法中断了t1的执行,释放了t1线程获取到的所有锁,中断后t2获取到了o1和o2锁,开始执行直到结束,而t1却夭折在了sleep的时候,sleep后的代码没有执行。

因此使用stop我们在不知道线程到底运行到了什么地方,暴力的中断了线程,如果sleep后的代码是资源释放、重要业务逻辑等比较重要的代码的话,亦或是其他线程依赖t1线程的运行结果,那直接中断将可能造成很严重的后果。

那么不建议使用stop中断线程我们应该怎么去优雅的结束一个线程呢,我们可以存java开发者的注释中窥探到一种解决方案:

1fdbe836-e009-11eb-9e57-12bb97331649.png

可以看到java开发者推荐我们使用以下两种方法来优雅的停止线程:

1.定义一个变量,由目标线程去不断的检查变量的状态,当变量达到某个状态时停止线程。

代码举例如下:

volatile static boolean flag=false;

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

Object o1=new Object();

Thread t1=new Thread(()-》{

synchronized (o1)

{

try {

System.out.println(“t1获取到锁”);

while (!flag)

Thread.sleep(5000);//执行业务逻辑

System.out.println(“t1结束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

t1.start();

Thread.sleep(1000);

Thread t2=new Thread(()-》{

synchronized (o1)

{

try {

System.out.println(“t2获取到锁”);

Thread.sleep(5000);//执行业务逻辑

System.out.println(“t2结束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

t2.start();

flag=true;

}

运行结果:

1ffacdc8-e009-11eb-9e57-12bb97331649.png

2.使用interrupt方法中断线程。

代码举例如下:

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

Object o1=new Object();

Thread t1=new Thread(()-》{

synchronized (o1)

{

System.out.println(“t1获取到锁”);

while (!Thread.currentThread().isInterrupted()) {

for (int i = 0; i 《 100; i++) {

if(i==50)

System.out.println();

System.out.print(i+“ ”);

}

System.out.println();

}

System.out.println(“t1结束”);

}

});

t1.start();

Thread t2=new Thread(()-》{

synchronized (o1)

{

try {

System.out.println(“t2获取到锁”);

Thread.sleep(5000);//执行业务逻辑

System.out.println(“t2结束”);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

});

t2.start();

t1.interrupt();

}

运行结果:

202dbdb4-e009-11eb-9e57-12bb97331649.png

我们用while (!Thread.currentThread().isInterrupted())来不断判断当前线程是否被中断,中断的话则让线程自然消亡并释放锁。可以看到调用interrupt方法后并不会像stop那样暴力的中断线程,会等到当前运行的逻辑结束后再检查是否中断,非常的优雅。另外,关注Java知音公众号,回复“后端面试”,送你一份面试题宝典!

注:运行举例代码可能不会打印出数字,这是因为t1线程运行到while(!Thread.currentThread().isInterrupted())时,主线程已经调了interrupt方法,因此多次运行可能会打印出数字。

二、suspend的落幕suspend方法的作用是挂起某个线程直到调用resume方法来恢复该线程,但是调用了suspend方法后并不会释放被挂起线程获取到的锁,正因如此就给suspend和resume这哥俩贴上了容易引发死锁的标签,当然这也正是导致suspend和resume退出历史舞台的罪魁祸首。同样我们看看java开发者为suspend的淘汰给出的理由:

206731fc-e009-11eb-9e57-12bb97331649.png

从中我们可以得出以下结论:

suspend具有天然的死锁倾向

当某个线程被suspend后,该线程持有的锁不会被释放,其他线程也就不能访问这些资源

suspend某个线程后,如果在resume的过程中出现异常导致resume方法执行失败,则lock无法释放,导致死锁

接下来模拟一下由suspend引起的死锁场景,Talk is cheap,show my code:

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

Object o1=new Object();

Object o2=new Object();

Thread t1=new Thread(()-》{

synchronized (o1)

{

System.out.println(“t1获取到o1锁开始执行”);

try {

Thread.sleep(5000);//模拟执行业务逻辑

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“t1执行结束”);

}

});

t1.start();

Thread t2=new Thread(()-》{

synchronized (o2)

{

System.out.println(“t2获取到o2开始执行”);

try {

Thread.sleep(2000);//执行耗时业务

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (o1)

{

System.out.println(“t2获取到o1锁开始继续执行”);

}

System.out.println(“t2执行结束”);

}

});

t2.start();

Thread.sleep(1000);

t1.suspend();

//假设抛出了一个未知异常

int i=1/0;

t1.resume();

}

运行结果:

20736242-e009-11eb-9e57-12bb97331649.png

可以看到,整个程序卡的死死的,在调用resume恢复t1线程之前抛出了一个未知异常,导致t1一直挂起进而无法释放o1锁,而t2需要获取到o1锁后才能继续执行,但苦苦等待,奈何o1被t1拿捏的死死的,从此整个程序就陷入了无尽的等待中----死锁。

作者丨浪舟子

blog.csdn.net/qq_40400960/article/details/112651249

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 中断
    +关注

    关注

    5

    文章

    895

    浏览量

    41366

原文标题:为什么强烈不推荐使用stop、suspend方法来中断线程?

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    断连块应用于飞控测试环境断线测试箱

    断连块概述Overviewofdisconnectedblocks断连块是一种用于电路中断连接的连接器,广泛应用于电子测试设备和通信系统中。它能够在特定条件下,通过手动插拔精准地中断电路连接,以此
    的头像 发表于 10-09 08:06 127次阅读
    断连块应用于飞控测试环境<b class='flag-5'>断线</b>测试箱

    控制回路断线可能原因及如何处理

    控制回路断线是电气系统中常见的故障之一,它可能导致设备无法正常工作,甚至引发安全事故。本文将分析控制回路断线的可能原因,并提出相应的处理方法。 一、控制回路断线的可能原因 接线错误 接
    的头像 发表于 08-23 16:36 1415次阅读

    armv8在启动刚开始时调用了关中断,一直到切换第一个线程在哪里开启的中断呢?

    例如当前使用的armv8芯片,在启动刚开始时调用了关中断,一直到切换第一个线程在哪里开启的中断呢? int rtthread_startup(void
    发表于 07-04 07:00

    AD8338有没有可行的方法来测量大增益?

    AD8338是一款VGA芯片,可变增益范围为-10dB至70dB。然而,理论上的70dB增益过大,导致来自源的输入信号非常小,容易受到干扰,导致70dB增益未得到验证。有没有可行的方法来测量大增益?
    发表于 05-21 07:06

    STM32F107的OTG在stop模式下无法通过EXTI_18唤醒,没有中断产生是怎么回事?

    作为device,想验证EXTI_18的中断,配置好EXTI初始化,但只有在enable suspend int后,在插拔USB线缆时才会进OTG_FS_WKUP_IRQHandler,如果配置设备
    发表于 05-06 08:59

    使用FreeRTOS创建的DHCP线程里面的DHCP是在哪里定义的?

    请教下,使用 FreeRTOS 创建的 DHCP 线程里面的 DHCP 是在哪里定义的,貌似没有找到 ? FreeRTOS 版本 v9.0.0 具体如下: // 创建 DHCP 线程 void
    发表于 04-30 07:34

    STM8L151不能同时初始化同一中断线的两个管脚怎么解决?

    请问,STM8中断问题,不能同时初始化同一中断线的两个管脚,比如PC4,PD4,对应中断线EXTI4,如果同时初始化PC4/PD4的终端,则中断不能正常工作。PD4对应按键
    发表于 04-28 07:32

    stm32外部中断不能唤醒stop休眠模式怎么解决?

    按键引脚设置成外部中断方式,可以正常唤醒stop模式;但是充电口设置成外部中断,却无法唤醒stop休眠!!!配置都是一样的,按键下降沿触发,充电检测是上升沿触发。 有可能是什么原因,
    发表于 04-26 06:11

    如果是使用六步方波的方法来控制电机,要如何实现过电流保护?

    请问一下如果是使用六步方波的方法来控制电机,要如何实现过电流保护? 以免电流过大造成板子损坏
    发表于 04-22 08:10

    stm32f4如何禁止usb suspend或修改进入suspend的时间?

    手册说是usb设备在3ms没有数据就会进入 suspend mode,哪里可以修改时间,或者把3ms修改成3秒,或者禁止usb 进入suspend. DCD_HandleUSBSuspend_ISR USBD_Suspend D
    发表于 04-02 08:06

    加湿器的作用及好处与坏处 加湿器的正确使用方法

    疾病的发生。然而,过度使用加湿器或错误使用也可能会导致空气中的细菌和霉菌增加,对健康产生负面影响。以下是关于加湿器的作用及好处与坏处以及正确使用方法。 加湿器的作用及好处: 改善干燥环境:加湿器能够在干燥环境
    的头像 发表于 01-25 09:52 1558次阅读

    火线断线和零线断线的危害

    在我们三相四线的供电回路里,三根火线和一根零线都是不能缺少的,任何一根断线都会给我们的用电设备造成严重的危害,那么火线断线和零线断线的造成后果是一样的吗?
    的头像 发表于 01-17 10:02 2730次阅读
    火线<b class='flag-5'>断线</b>和零线<b class='flag-5'>断线</b>的危害

    PT断线是什么?为什么说PT断线影响很严重?

    PT断线是什么?为什么说PT断线影响很严重? PT断线是指电压互感器的一种故障状态,即PT缺乏或中断了电压信号的传输。PT作为一种重要的电气元件,主要用于将高压系统的电压降到安全范围内
    的头像 发表于 12-26 16:01 2937次阅读

    什么是PT断线 PT断线的影响

    我们首先了解PT断线是什么。PT是电压互感器的英文符号,电压互感器断线,在电力电气生产活动中是一种比较常见的故障。一旦PT断线失压,对保护、计量、测量等操作的准确性和可靠性,均会产生至关重要
    的头像 发表于 11-24 17:25 1845次阅读

    一种简单的方法来将振荡器相位噪声转换为时间抖动

    电子发烧友网站提供《一种简单的方法来将振荡器相位噪声转换为时间抖动.pdf》资料免费下载
    发表于 11-23 15:15 0次下载
    一种简单的<b class='flag-5'>方法来</b>将振荡器相位噪声转换为时间抖动