zoukankan      html  css  js  c++  java
  • 并发编程(七)线程如何优雅地终止

    一、停止线程的几种方法

    • 使用退出标志,使线程正常退出,也就是当 run() 方法完成后线程中止。
    • 使用interrupt()方法中断线程。
    • 使用stop()方法强行终止线程,但是不推荐使用这个方法,该方法已被弃用!!!

    二、方法详解

    使用标志位终止线程

    /**
     * 设置标识位停止线程
     */
    public class MyThreadStop {
    
        //计数
        private static int count = 0;
        //退出标识符
        public static boolean exit = false;
    
    
        /**
         * 核心线程
         */
        public static void main(final String[] arguments) throws InterruptedException {
            Thread t = new Thread(new TestThread());
            t.start();
        }
    
        /**
         * 同步方法
         */
        public static synchronized void countNum() {
            for (int i = 0; i < 100000; i++) {
                if (count >= 500000) {
                    exit = true; //修改标志位,退出线程
                } else {
                    count++;
                    System.out.println(count);
                }
            }
        }
    
        /**
         * 线程实体(实现Runnable接口)
         */
        static class TestThread implements Runnable {
    
            public void run() {
                while (!exit) {//当标识符没设置停止时,一直做参数递增
                    countNum();
                }
            }
        }
    }

    使用interrupt()方法中断线程

    • interrupt() 方法并不像在 for 循环语句中使用 break 语句那样干脆,马上就停止循环。
    • 调用 interrupt() 方法仅仅是在当前线程中打一个停止的标记,并不会立即终止线程。
    • 至于目标线程收到通知后会如何处理,则完全由目标线程自行决定。
    /**
     * interrupt()方法停止线程
     */
    public class MyThreadStop {
    
        //计数器
        private static int count = 0;
    
        /**
         * 核心线程
         */
        public static void main(final String[] arguments) throws InterruptedException {
            Thread t = new Thread(new TestThread());
            t.start();
            //休眠一会儿,然后中断
            t.sleep(200);
            t.interrupt();
        }
    
        /**
         * 同步方法
         */
        public static synchronized void countNum() {
            for (int i = 0; i < 500000; i++) {
                count++;
                System.out.println(count);
            }
        }
    
        /**
         * 线程实体(实现Runnable接口)
         */
        static class TestThread implements Runnable {
            public void run() {
                countNum();
            }
        }
    }

      上面的例子我们发现,好像interrupt方法并没有马上停止线程,还是继续跑完了,这是由于interrupt() 方法仅仅是在当前线程中打一个停止的标记,并不会立即终止线程。 至于目标线程收到通知后会如何处理,则完全由目标线程自行决定。

      我们可以改造一下~

    /**
     * interrupt()方法停止线程
     */
    public class MyThreadStop {
    
        //计数器
        private static int count = 0;
    
        /**
         * 核心线程
         */
        public static void main(final String[] arguments) throws InterruptedException {
            Thread t = new Thread(new TestThread());
            t.start();
            //休眠一会儿,然后中断
            t.sleep(200);
            t.interrupt();
        }
    
    
        /**
         * 线程实体(实现Runnable接口)
         */
        static class TestThread implements Runnable {
            public void run() {
                for (int i = 0; i < 500000; i++) {
                    //判断线程是否被通知中断
                    if (Thread.currentThread().isInterrupted()) {
                        //处理中断逻辑
                        break;
                    }
                    count++;
                    System.out.println(count);
                }
            }
        }
    }

      可以发现,在加入中断判断以后,线程停止了工作

      PS:当线程被 sleep() 休眠时,如果被中断,就会抛出一个 InterruptedException异常。

      PS:Thread.sleep() 方法由于中断而抛出的异常,是会清除中断标记的,线程后面的代码会继续执行

    stop()方法

      stop()方法停止线程的方式相当粗暴,直接停止线程工作,相当不安全,虽然现在已经弃用,还是简单的了解一下吧。

      为什么弃用stop:

    • 调用 stop() 方法会立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 语句中的,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。
    • 调用 stop() 方法会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题。

    好文推荐:

  • 相关阅读:
    Func<T, TResult> 委托的由来和调用和好处(为了高大上,为了白富美)
    $(function(){})和jQuery(function(){})
    把一个类(或者Object)转换成字典
    MVC 控制器向View传值的三种方法
    @html.ActionLink的几种参数格式
    你给老板谈工资,老板给你谈发展.之后发生的事...
    2015-11-5 关于编译的听课笔记
    2015-10-29 韦东山OK6410 第一天课程笔记
    2015-10-26 逻辑运算符使用分析
    2015-10-26 一些位运算符 课程笔记
  • 原文地址:https://www.cnblogs.com/riches/p/12023692.html
Copyright © 2011-2022 走看看