美文网首页
Java面试题-线程篇-(2)如何优雅的停止线程

Java面试题-线程篇-(2)如何优雅的停止线程

作者: wyn_做自己 | 来源:发表于2023-08-29 09:08 被阅读0次

在 Java 中停止线程的实现方法有以下 3 种:

  1. 自定义中断标识符,停止线程。

  2. 使用线程中断方法 interrupt() 停止线程。

  3. 使用 stop()方法 停止线程。

    那么如何优雅的停止线程呢?这三个方法中推荐的是使用interrupt()方法,下面详细来说明一下:

1、自定义中断标识符停止线程

自定义中断标识符就是在程序中定义一个变量来决定线程是否要中断执行,具体实现代码如下:

class FlagThreadDemo extends Thread {
    // 自定义中断标识符
    public volatile boolean isInterrupt = false;
    @Override
    public void run() {
        // 如果为 true -> 中断执行
        while (!isInterrupt) {
            // 业务逻辑处理
        }
    }
}

自定义中断标识符的问题在于:线程中断的不够及时。因为线程在执行过程中,无法调用 while(!isInterrupt) 来判断线程是否为终止状态,它只能在下一轮运行时判断是否要终止当前线程,所以它中断线程不够及时,代码如下:

class InterruptFlagDemo {
    // 自定义的中断标识符
    private static volatile boolean isInterrupt = false;

    public static void main(String[] args) throws InterruptedException {
        // 创建可中断的线程实例
        Thread thread = new Thread(() -> {
            while (!isInterrupt) { // 如果 isInterrupt=true 则停止线程
                System.out.println("thread 执行步骤1:线程即将进入休眠状态");
                try {
                    // 休眠 1s
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("thread 执行步骤2:线程执行了任务");
            }
        });
        thread.start(); // 启动线程

        // 休眠 100ms,等待 thread 线程运行起来
        Thread.sleep(100);
        System.out.println("主线程:试图终止线程 thread");
        // 修改中断标识符,中断线程
        isInterrupt = true;
    }
}

以上代码的执行结果如下图所示:


image.png

我们期望的是:线程执行了步骤 1 之后,收到中断线程的指令,线程直接中断,不会再执行步骤 2 了,但从上述执行结果可以看出,使用自定义中断标识符是没办法实现我们预期的结果的,这就是自定义中断标识符,响应不够及时的问题。

2、调用interrupt()方法停止线程

使用 interrupt() 方法可以给执行任务的线程,发送一个中断线程的指令,它并不会直接中断线程,而是发送一个中断线程的信号给要被中断的线程,它把是否中断线程的主动权交给开发人员。开发人员可以通过Thread.currentThread().isInterrupted()判断出当前线程是否收到中断指令,然后再做相应处理,比如说收到中断指令我就停止继续执行相关业务逻辑处理啊,或者我不理会这个中断指令,继续处理相关业务逻辑,亦或者收到中断指令我就去做其他处理,这都是可以的。相比于自定义中断标识符而言,它能更及时的接收到中断指令,如下代码所示:

public static void main(String[] args) throws InterruptedException {
    // 创建可中断的线程实例
    Thread thread = new Thread(() -> {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("thread 执行步骤1:线程即将进入休眠状态");
            try {
                // 休眠 1s
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("thread 线程接收到中断指令,执行中断操作");
                // 中断当前线程的任务执行
                break;
            }
            System.out.println("thread 执行步骤2:线程执行了任务");
        }
    });
    thread.start(); // 启动线程

    // 休眠 100ms,等待 thread 线程运行起来
    Thread.sleep(100);
    System.out.println("主线程:试图终止线程 thread");
    // 修改中断标识符,中断线程
    thread.interrupt();
}

以上代码的执行结果如下图所示:


image.png

从上述结果可以看出,线程在接收到中断指令之后,立即中断了线程,相比于上一种自定义中断标识符的方法来说,它能更及时的响应中断线程指令

3、调用stop()方法停止线程

stop()方法虽然可以停止线程,但它已经是不建议使用的废弃方法了,这一点可以通过 Thread 类中的源码发现,stop 源码如下:


image.png

从上面的图片可以看出,stop 方法是被 @Deprecated 修饰的不建议使用的过期方法,并且在注释的第一句话就说明了 stop 方法为非安全的方法。在最新版本 Java 中,此方法已经被直接移除了,所以强烈不建议使用。

那为什么废弃stop()方法呢:

因为 stop 方法会直接停止线程,这样就没有给线程足够的时间来处理停止前的保存工作,就会造成数据不完整的问题,因此不建议使用。再举一个例子,比如说你这个线程占用了一把锁,然后你调用stop直接把线程给停掉了,但你这把锁还没有释放,这样就导致了,你这个线程都不存在了,而这把锁却一直被占用着,这样的话,其他线程就会永远都拿不到这把锁。

这里还有一点要说明,stop()方法会释放掉线程占用的Synchronized锁,而不会自动释放ReentrantLock锁,这个主要就是ReentrantLock锁是通过lock()方法加锁,unlock()方法释放锁,而当我们执行stop()方法的时候,很可能就是执行了lock()方法之后,还没执行unlock()方法的时候,执行了stop()方法,这样就导致了ReentrantLock锁没有释放。

总结

本文介绍了停止线程的 3 种方法:

  1. 自定义中断标识符的停止方法,此方法的缺点是不能及时响应中断请求;
  2. 使用 interrupt 中断线程方法,此方法是发送一个中断信号给线程,它可以及时响应中断,也是最推荐使用的方法;
  3. 最后是 stop 方法,但此方法已经是过时的不建议使用的方法,在 Java 最新版本中已经被直接移除了,所以不建议使用。

相关文章

  • 一个简单的带中断策略的Thread用例

    使用: 如何优雅的"停止"一个正在运行的JAVA线程如何正确地停止一个线程?关闭线程的正确方法:“优雅”的中断Ja...

  • JAVA线程面试题书目录

    JAVA线程面试题之1) 什么是线程? JAVA线程面试题之2) 线程和进程有什么区别? JAVA线程面试题之3)...

  • java线程面试题大全

    java线程面试题大全1、15个Java线程并发面试题和答案2、15个高级Java多线程面试题及回答3、GC线程是...

  • Java多线程(二)

    Java多线程(二) 上一篇“Java多线程(一)”主要讨论的是线程的创建,本章主要讨论停止线程。 1.概述 停止...

  • java线程面试题_2019java面试题库

    1、15个Java线程并发面试题和答案2、15个高级Java多线程面试题及回答3、GC线程是否为守护线程?4、Ha...

  • 2018-02-01

    50道java线程面试题 50道Java线程面试题 下面是Java线程相关的热门面试题,你可以用它来好好准备面试。...

  • java并发之守护线程

    java中有两种线程,用户线程和守护线程用户线程:主线程停止时,用户线程不会停止守护线程:主线程停止时,守护线程也...

  • 总结多线程与设计模式+synchronized+性能+高吞吐+死

    Java线程 Java语言的线程 何谓线程 线程启动 线程的暂时停止 线程的共享互斥 线程的协调 线程的状态转移 ...

  • 停止及中断运行的线程

    停止线程的方式 在 Java 中停止线程的方式有三种:1、线程的 run 方法执行到最后,线程正常结束并退出;2、...

  • 多线程面试题(这个是复制别人的,感觉很好)

    50道Java线程面试题 下面是Java线程相关的热门面试题,你可以用它来好好准备面试。 1) 什么是线程? 线程...

网友评论

      本文标题:Java面试题-线程篇-(2)如何优雅的停止线程

      本文链接:https://www.haomeiwen.com/subject/vfpnmdtx.html