为什么 Thread.stop、Thread.suspend、Thread.resume、Runtime.runFinalizersOnExit 都被废弃了

JAVA herman 321浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领

最近一个同学发来消息说,公司里有一段代码使用的线程经常会发生一些莫名其妙的问题。让我帮忙看看,我仔细看了很多遍线程的相关代码。最后注意到了 InterruptException 异常,把想法和 demo 代码给他说了后,问题果真被解决了。

危险代码

关于这个问题,我通过一段简化的代码来给大家演示一下。

public class ThreadSafe extends Thread {
    public void run() { 
        while (true){
            try{
                Thread.sleep(5*1000);//阻塞5妙
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    } 
}

看到上面这段 demo 了吗?多简单,多熟悉啊。但是有一个问题,90% 的人可能都没有遇到,但确实存在的。

我们先看 Thread.sleep 为什么要抛出一个异常?其实,很简单,你仔细想想,如果你正在睡觉的时候,突然有人打扰到你,是不是就相当于发生了中断睡觉的异常。而 InterruptedException 这个异常的发生就是因为有人打扰了这个线程的休眠。

谁打扰的呢?就是调用这个线程的 interrupt() 方法的对象。OK ,现在我们来看看,当我调用上面这个线程的 interrupt() 方法的时候,它正在休眠,那么就会发生 InterruptedException 异常。而这个时候,你却把 InterruptedException 异常捕捉了,于是本该停止的线程就行失去刹车的车辆一样裸奔了。

而正确的处理 InterruptedException 异常的方法是,捕捉异常之后,加一个 break,终止线程。除此之外,结束一个线程推荐的方法有 3 种。

public class ThreadSafe extends Thread {
    public volatile boolean exit = false; 
        public void run() { 
        while (!exit){// 1、标志位结束
            //do something
        }
        while (!isInterrupted()){//2、判断 interrupted 状态
            //do something, but no throw InterruptedException
        }
        while (!isInterrupted()){ //3、非阻塞过程中通过判断中断标志来退出
            try{
                Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出
            }catch(InterruptedException e){
                e.printStackTrace();
                break;//捕获到异常之后,执行break跳出循环。
                // 或者使用下面的代码
                // 重新设置中断标志位 
                Thread.currentThread().interrupt();
            }
        }
    } 
}

现在我们再来看看为什么 Thread.stop、Thread.suspend、Thread.resume、Runtime.runFinalizersOnExit 这几个方法都被废弃了。这是因为,这几个操作太暴力了。stop() 方法会真的杀死线程,不给线程喘息的机会,如果线程持有 ReentrantLock 锁,被 stop() 的线程并不会自动调用 ReentrantLock 的 unlock() 去释放锁,那其他线程就再也没机会获得 ReentrantLock 锁,这实在是太危险了。所以该方法就不建议使用了,类似的方法还有 suspend() 和 resume() 方法、Runtime.runFinalizersOnExit() 方法,这 3 个方法同样也都不建议使用了。危害性都非常大,所以被废弃的方法你千万不要使用!

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号1:xmtxtt(5000人已满),微信号2:codedq(5000人已满),微信号3:xttblog(超2800)。备注:“xttblog”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » 为什么 Thread.stop、Thread.suspend、Thread.resume、Runtime.runFinalizersOnExit 都被废弃了