zoukankan      html  css  js  c++  java
  • 007 优雅的关闭线程

    一 .概述

     在jdk之中之前又一个stop方法可以关闭线程,但是那个方法存在线程安全的问题,现在已经被废除掉了.

    之后就没有出现关闭线程的方法了.

    但是在我们的使用过程之中,我们需要关闭线程,这个时候,我们就需要用其它的方式来完成线程的关闭操作.


    二 . 使用标记位完成

    public class StopThread {
    
        private static class task implements Runnable {
            // 标记位
            private volatile boolean flag = true;
    
            public void run() {
                while (flag) {
                    System.out.println("running ...");
                }
            }
    
            public void shutdown() {
                this.flag = false;
            }
        }
    
        public static void main(String[] args) throws Exception {
            task task = new task();
            Thread thread = new Thread(task);
            thread.start();
            // 主线程休眠三秒之后 修改标记位
            TimeUnit.SECONDS.sleep(3);
            task.shutdown();
        }
    }

    以上的方式时可以完成任务的,但是需要不断的监听标记位.


    三 . 使用interrupt的方式

    public class InterruptThread {
    
        private static class Task implements Runnable {
            public void run() {
                try {
                    for (;;) {
                        TimeUnit.MICROSECONDS.sleep(100);
                        System.out.println("thread is running ... ");
                    }
                } catch (Exception e) {
                    return ; 
                }
    
            }
        }
    
        public static void main(String[] args) throws Exception {
            Thread thread = new Thread(new Task());
            thread.start();
            // 主线程休眠3秒之后,主动打断任务线程
            TimeUnit.SECONDS.sleep(3);
            thread.interrupt();
        }
    }

    在主线程休眠3秒之后,主动打断子线程,子线程的sleep方法会抛出异常我们捕获异常就能终止线程的运行了.

    在这里我们使用的是sleep方法,同时我们也可以用判断的方式.

    public class InterruptThread {
    
        private static class Task implements Runnable {
            public void run() {
                for (;;) {
                    // TimeUnit.MICROSECONDS.sleep(100);
                    if (!Thread.interrupted())
                        System.out.println("thread is running ... ");
                    else
                        return;
                }
    
            }
        }
    
        public static void main(String[] args) throws Exception {
            Thread thread = new Thread(new Task());
            thread.start();
            // 主线程休眠3秒之后,主动打断任务线程
            TimeUnit.SECONDS.sleep(3);
            thread.interrupt();
        }
    }

    相对来说,我们用判断的方式还是比较好的.


    四 .暴力停止线程

    当我们的任务花费的时间比较长的时候,我们的循环判断是根本没有触发的时候,这个时候我们就需要使用暴力的方式强制线程停止.

    public class ThreadService {
        //执行线程,相当于一个主线程...
        private Thread executeThread;
    
        public void startThread(final Runnable task) {
            // 创建执行线程,这个线程就是一个主线程
            executeThread = new Thread() {
                @Override
                public void run() {
                    // 开启子线程
                    Thread childThread = new Thread(task);
                    // 设置子线程为守护进程
                    childThread.setDaemon(true);
                    // 开启子线程的任务
                    childThread.start();
                    // 父线程一直线循环
                    try {
                        //主线程一直让子线程运行
                        childThread.join();
                        
                    } catch (InterruptedException e) {
                        // 当主线程被打断的时候,直接终止自己的运行
                        // nothing to do
                        System.out.println("收到了终结主线程的信号了,现在我需要停止了");
                        System.out.println("我带的守护线程也需要终结了..");
                        return ; // 终结主线程,子线程随之被杀死
                    }
                }
            };
            //开启执行线程
            executeThread.start();
        }
    
        public void shutdown() {
            // 打断主线程 --那么守护进程就被终结了
            this.executeThread.interrupt();
        }
    }

    我们创建了一个线程服务类,这个服务类由两个方法

    [1]开启一个线程

    [2]终结一个线程

    原理 :  在这个线程类里面有有一个执行线程,在开启的时候会初始化这个线程任务,这个线程任务很简单.

        [1] 创建一个子线程,将线程逻辑交给子线程.其中子线程被设置为守护线程.

        [2]然后主线程自己阻塞,直到子线程运行完成或者自己的阻塞被打断.

    我们的shutdown方法的实现很简单,那就是直接打断执行线程的阻塞状态.一旦执行贤臣被打断,会进入catch语句,语句里面会终结这个函数,那么子线程也被终止了.


    五 .总结

    现在我们看到线程的终结还需要自己去封装一个服务,到后面我们可以看到大神

    李狗的代码,看它是如何解决这种问题的.

    这里只是练习一下API而已.    

      

  • 相关阅读:
    利用Navicat向MySQL数据库中批量插入多条记录的方法
    《Spring MVC+MyBatis快速开发与项目实战》-黄文毅2019:一书的源码和配套视频下载地址
    MySQL数据库建库时SQL语句中数据库名、表名用引号的问题以及COLLATE utf8_general_ci的含义
    [转]层行列和经纬度坐标之间的相互转化方法(谷歌地图)
    [Web 前端] VML、SVG、Canvas简介
    [Android Pro] 完美解决 No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
    [Android Pro] so 动态加载—解决sdk过大问题
    [Android Pro] https://blog.csdn.net/gaugamela/article/details/79143309
    [web前端] 去哪儿网前端架构师司徒正美:如何挑选适合的前端框架?
    [web前端] yarn和npm命令使用
  • 原文地址:https://www.cnblogs.com/trekxu/p/8970849.html
Copyright © 2011-2022 走看看