【多线程并发编程】九 线程Thread的停止

程序猿学社的GitHub,欢迎Star
https://github.com/ITfqyd/cxyxs
本文已记录到github,形成对应专题。

前言

最近,有一个网友,在某技术群里,提出一个问题,线程怎么停止,有什么好的方法,群里有不少人的回答,都是直接调用stop方法。我的回答是这样的,各位可以帮我看看对不对。因为停止线程也没有我们想象中的那么简单。

方法一:stop方法

在这里插入图片描述

  • 通过查看Thread类的源码,我们可以发现stop方法上面有 @Deprecated注解,这个方法已经out。
  • stop方法会导致代码逻辑不完整,他收到停止命令后,会立即停止。
  • stop方法会破坏原子逻辑。

过时

@Deprecated注解表示该方法是过时方法。

代码逻辑没有运行完,就退出

package com.cxyxs.thread.nine;

/**
 * Description:验证业务逻辑
 * 转发请注明来源  程序猿学社 - https://ithub.blog.csdn.net/
 * Author: 程序猿学社
 * Date:  2020/2/27 10:01
 * Modified By:
 */
public class LogicIncomplete implements Runnable{
    @Override
    public void run() {
        try {
            System.out.println("正在运行代码中");
            Thread.sleep(1000);
            System.out.println("关键代码!");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        LogicIncomplete logic = new LogicIncomplete();
        Thread thread = new Thread(logic);
        thread.start();
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.stop();
    }
}

在这里插入图片描述

  • 子线程调用stop后,立马就停止,因为该进程内,没有用户线程,所以整个程序也自动退出了。
  • 按照正常的退出逻辑,应该会输出"关键代码"这段话。例如,定时把15分钟的图片,10秒一张,合成一张图片,流程是先把图片打上水印,放到某个临时文件夹,再合成视频,再删除临时文件,如果中途调用stop方法,可能会导致本地有很多临时文件。
  • 这种方式因为不安全,太粗暴,所以,不建议使用。

方法二:通过标识位,停止线程

package com.cxyxs.thread.nine;

/**
 * Description:通过设置标志位,停止线程
 * 转发请注明来源  程序猿学社 - https://ithub.blog.csdn.net/
 * Author: 程序猿学社
 * Date:  2020/2/27 14:32
 * Modified By:
 */
public class FlagThread implements  Runnable{
    private  boolean flag = true;


    @Override
    public void run() {
        int count=1;
        while (flag){
            System.out.println("程序猿学社:"+count);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            count++;
            System.out.println("逻辑已跑完!");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        FlagThread flagThread = new FlagThread();
        Thread thread = new Thread(flagThread);
        thread.start();

        Thread.sleep(5000);
        flagThread.flag  = false;
    }
}

在这里插入图片描述

  • 主要逻辑,有两个线程,main线程和我们自定义的线程,main线程延迟5秒后,直接通过标识位,把自定义的那个线程停止。
  • 通过观察结果,我们可以发现,通过这种方式停止,他会保证run方法里面的业务逻辑都跑完。
  • 使用该方面一定要给出终止条件,不然开销成本不小。
  • 如果这个线程,需要一直运行,最好,还是适当的让出资源。

方法三:通过标识位+异常处理结束线程

package com.cxyxs.thread.nine;

/**
 * Description:转发请注明来源  程序猿学社 - https://ithub.blog.csdn.net/
 * Author: 程序猿学社
 * Date:  2020/2/27 14:55
 * Modified By:
 */
public class InterruptThread implements  Runnable{
    private  static  boolean flag = true;
    @Override
    public void run() {
        int count=1;
        while (flag){
            try {
                System.out.println("程序猿学社:"+count);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                this.flag = false;
                e.printStackTrace();
            }finally {
                count++;
                System.out.println("逻辑已跑完!");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        InterruptThread interruptThread = new InterruptThread();
        Thread thread = new Thread(interruptThread);
        thread.start();

        Thread.sleep(5000);
        thread.interrupt();
    }
}

在这里插入图片描述

  • 通过测试,我们可以发现,通过异常+interrupt方式,我们可以顺利的结束线程,也不会存在不安全的问题。
  • interrupt是无法停止线程的,只是做个标记状态,具体他的使用方法,我们后续再一步一步的分析他的源码。
    **总结:**创建线程,建议使用线程池的方式,里面shutdown方法可以停止线程。
发布了286 篇原创文章 · 获赞 557 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/qq_16855077/article/details/104529660