zoukankan      html  css  js  c++  java
  • 并发编程:线程的中断

    1.使用interrupt()中断线程

    首先来看一段代码:

    public class InterruptTest01 {
    
        public static class m1 implements Runnable {
    
            public void run() {
                try {
                    System.out.println("in run() - 睡眠20秒");
                    Thread.sleep(20000);
                    System.out.println("in run() - 线程唤醒");
                } catch (Exception e) {
                    System.out.println("in run() - 线程睡眠中被打断了");
                    // 如果没有return,线程不会实际被中断,它会继续打印下面的信息
                    System.out.println("t线程sleep中被打断后中断标志位状态:" + Thread.interrupted());
                    return;
                }
                System.out.println("in run() - 线程正常的消亡了");
            }
        }
    
    
        public static void main(String[] args) {
            m1 si = new m1();
            Thread t = new Thread(si);
            // 开启t线程
            t.start();
            System.out.println("调用interrupt方法前,t线程的中断状态:" + t.isInterrupted());
            try {
                // 仅仅是做标记
                t.interrupt();
                System.out.println("调用interrupt方法后,t线程的中断状态:" + t.isInterrupted());
                // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.err.println("主线程catch块出问题了");
            }
            System.out.println("in main() - 主线程终止了");
        }
    
    }

    执行结果:

    调用interrupt方法前,t线程的中断状态:false
    调用interrupt方法后,t线程的中断状态:true
    in run() - 睡眠20秒
    in run() - 线程睡眠中被打断了
    t线程sleep中被打断后中断标志位状态:false
    in main() - 主线程终止了

     分析:Thread.sleep(2000)这个方法需放在interrupt方法之后,如果放在之前,会出现中断标志位全为false的情况

    如果只是单纯的调用interrupt()方法,线程并没有实际被中断,会继续往下执行。

    比如:

    public class InterruptTest01 {
    
        public static class m1 implements Runnable {
    
            public void run() {
                while (true){
                    System.out.println("我是不会中断的了");
                }
            }
        }
    
    
        public static void main(String[] args) {
            try {
                m1 si = new m1();
                Thread t = new Thread(si);
                // 开启t线程
                t.start();
                System.out.println("调用interrupt方法前,t线程的中断状态:" + t.isInterrupted());
                // 仅仅是做标记
                t.interrupt();
                System.out.println("调用interrupt方法后,t线程的中断状态:" + t.isInterrupted());
                // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.err.println("主线程catch块出问题了");
            }
            System.out.println("in main() - 主线程终止了");
        }
    
    }

    结果就是自旋

    应当在run方法加上中断标志位的判断

        public static class m1 implements Runnable {
            public void run() {
                while (true){
                    if(Thread.interrupted()){
                        System.out.println("我竟然中断了");
                        return;
                    }
                    System.out.println("我是不会中断的了");
                }
            }
        }

    结果:

    调用interrupt方法前,t线程的中断状态:false
    调用interrupt方法后,t线程的中断状态:true
    我竟然中断了
    in main() - 主线程终止了

    2.网上说的待决中断

    意思就是:如果线程在调用sleep()方法前被中断,那么该中断称为待决中断,它会在刚调用sleep()方法时,立即抛出InterruptedException异常。

    public class PendingInterruptTest {
    
        public static void main(String[] args) {
            Thread.currentThread().interrupt();
            // 获取当前时间
            long startTime = System.currentTimeMillis();
            try {
                Thread.sleep(2000);
                System.out.println("主线程没有被打断");
            } catch (InterruptedException x) {
                System.out.println("主线程被打断,进入catch块");
            }
            // 计算中间代码执行的时间
            System.out.println("时间差 =" + (System.currentTimeMillis() - startTime));
        }
    
    }

    结果:

    主线程被打断,进入catch块
    时间差 =1

     3.interrupted() 和 isInterrupted() 的区别?

    首先看一段代码

    public class InterruptTest01 {
    
        public static class m1 implements Runnable {
            public void run() {
                System.out.println("我是不会中断的了");
            }
        }
    
    
        public static void main(String[] args) {
            try {
                m1 si = new m1();
                Thread t = new Thread(si);
                // 开启t线程
                t.start();
                System.out.println("调用interrupt方法前0,t线程的中断状态:" + t.interrupted());
                t.interrupt();
                System.out.println("调用interrupt方法后1,t线程的中断状态:" + t.interrupted());
                System.out.println("调用interrupt方法后2,t线程的中断状态:" + t.interrupted());
                // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.err.println("主线程catch块出问题了");
            }
            System.out.println("in main() - 主线程终止了");
        }
    
    }

    结果:

    调用interrupt方法前0,t线程的中断状态:false
    调用interrupt方法后1,t线程的中断状态:false 调用interrupt方法后2,t线程的中断状态:false 我是不会中断的了 in main() - 主线程终止了

    分析:结果竟然都是false,可见thread 线程并没有停止,而且调用 thread.interrupted() 结果是两个 false 表示线程一直在运行过程中。

    看官方解释:当前线程是指运行 this.interrupted() 方法的线程 。也就是说,当前线程并不是 t,并不是因为 t 调用了 interrupted() 方法就是当前线程。当前线程一直是 main 线程,它从未中断过,所以打印结果就是两个 false。

    改变:

    public class InterruptTest01 {
    
        public static class m1 implements Runnable {
            public void run() {
                System.out.println("我是不会中断的了");
            }
        }
    
    
        public static void main(String[] args) {
            try {
                m1 si = new m1();
                Thread t = new Thread(si);
                // 开启t线程
                t.start();
                System.out.println("调用interrupt方法前0,t线程的中断状态:" + Thread.interrupted());
                Thread.currentThread().interrupt();
                System.out.println("调用interrupt方法后1,t线程的中断状态:" + Thread.interrupted());
                System.out.println("调用interrupt方法后2,t线程的中断状态:" + Thread.interrupted());
                // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.err.println("主线程catch块出问题了");
            }
            System.out.println("in main() - 主线程终止了");
        }
    
    }

    结果:

    调用interrupt方法前0,t线程的中断状态:false
    调用interrupt方法后1,t线程的中断状态:true
    调用interrupt方法后2,t线程的中断状态:false
    我是不会中断的了
    in main() - 主线程终止了
    从上述结果中可以看出,方法 interrupted() 的确判断出当前线程是否已经停止,但是为什么第 2 个布尔值是 false 呢?
    文档中说的很详细,interrupted() 方法具有清除状态的功能,所以第二次的时候返回值是 false

    isInterrupt()方法代码

        public static void main(String[] args) {
            try {
                Thread t = Thread.currentThread();
                System.out.println("调用interrupt方法前0,t线程的中断状态:" + t.isInterrupted());
                t.interrupt();
                System.out.println("调用interrupt方法后1,t线程的中断状态:" + t.isInterrupted());
                System.out.println("调用interrupt方法后2,t线程的中断状态:" + t.isInterrupted());
                // 主线程休眠2秒,从而确保刚才启动的线程有机会执行一段时间
                Thread.sleep(2000);
                System.out.println("还在输出吗?");
            } catch (InterruptedException e) {
                System.err.println("主线程catch块出问题了");
            }
            System.out.println("in main() - 主线程终止了");
        }

    结果:

    调用interrupt方法前0,t线程的中断状态:false
    主线程catch块出问题了
    调用interrupt方法后1,t线程的中断状态:true
    调用interrupt方法后2,t线程的中断状态:true
    in main() - 主线程终止了
    线程一旦被中断,isInterrupted()方法便会返回true,而一旦sleep()方法抛出异常,它将清空中断标志,此时isInterrupted()方法将返回false

    总结:

    interrupted():测试 当前线程 是否已经是中断状态,执行后具有清除状态功能。
    isInterrupted():测试线程 Thread 对象 是否已经是中断状态,但不清楚状态标志。
  • 相关阅读:
    android 第三方开源库 学习汇总之Butter Knife
    android Gradle下载慢,使用阿里镜像
    android 第三方开源库 学习汇总
    <Android Studio> 4.Adapter的那些事 <一>
    <Android Studio> 3.打包APK
    <Android Studio> 2.APP开机启动
    <Android Studio> 1.如何APP配置权限
    Android源码分析(十七)----init.rc文件添加脚本代码
    Android源码分析(十六)----adb shell 命令进行OTA升级
    Android源码分析(十五)----GPS冷启动实现原理分析
  • 原文地址:https://www.cnblogs.com/zhangjianbing/p/9104633.html
Copyright © 2011-2022 走看看