• java多线程技术: interrupt() 中断线程, 优雅停止线程及原理


    MyThread.class

    package cn.yilong.edcsapiservice.thread;
    
    public class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("开始睡觉");
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("结束睡觉");
    
            synchronized (MyThread.class){
                for (int i=0; i<100; i++){
                    System.out.print(i+",");
                }
                System.out.println();
                String name = Thread.currentThread().getName();
                System.out.println(name + ": " + this.isInterrupted());
                System.out.println("test--------------------");
                System.out.println();
            }
    
        }
    }

    Run.class

    package cn.yilong.edcsapiservice.thread;
    
    public class Run2 {
    
        public static void main(String[] args) {
            Thread ct = Thread.currentThread();
            ct.setName("mainThread");
    
            try {
                MyThread t = new MyThread();
                t.setName("myThread");
                t.start();
    
                t.interrupt();  // 如果t线程已经结束,再调中断方法,不做任何处理
    
                synchronized (MyThread.class) {
                    String name = Thread.currentThread().getName();
                    System.out.println(name + ": " + t.interrupted()); //虽然是t线程调用,但底层真正调用不是t,而是当前main方法的线程, 执行实际操作是 Thread.currentThread().isInterrupted() 即mainThread线程
                    System.out.println(t.getName() + ": " + t.isInterrupted()); 
                    System.out.println("main-----------------------------");
                    System.out.println();
                }
    
    
            } catch (Exception e) {
                System.out.println("main catch");
                e.printStackTrace();
            }
        }
    }



    mainThread: false
    myThread: true
    main-----------------------------

    
    

    开始睡觉
    java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at cn.yilong.edcsapiservice.thread.MyThread.run(MyThread.java:8)
    结束睡觉
    0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,
    myThread: false
    test--------------------

    
    

    interrupt() 方法

    interrupt()本质是 给调用该方法的线程做一个标记, 这个标记默认初始值是: false, 调用后变成: true,  
    所以说, 做标记并不能停止这个线程.  而废弃的stop()方法是直接停止这个线程. 这是根本区别.
    
    线程对象调用interrupt()方法时, 我们想中断这个线程, 需要人为写逻辑进行中断,  
    通常存在两种情况(实际还有其他,源码注释上有解释):
    1. 线程状态:正在运行中,  此时如果t线程调用了interrupt()方法,  那么,t线程会立刻被做上标识: false变为true,  (当然,如果t线程调用interrupt()前刚好正常执行结束了,
    那么标记不会变更,依然时false) t线程如果还在执行中, 依然继续执行下去, 被标记不会受到任何影响(重点), 接着,我们在t线程的执行方法run()中通过调用 interrupted()或
    isInterrupted()来进行手动结束run()方法的执行. 啰嗦下: (
    1) t.interrupt()执行后, 打标记: false变true, run()方法中 t.interrupted()和t.isInterrupted()会获取到这个标记,值为false或true. (2) t.interrupted()方法注意两点:
    1.指代当前调用的线程, 也就是说, 如果在mian()方法中, 执行了t.interrupted()方法, 实际执行的并不是t线程, 而是main线程(特别注意)
    2.t.interrupted()方法执行后,会返回一个结果true或false, 同时它还会执行另一步操作: 将t线程标记的结果重置为默认初始值: false. 所以,不要第二次调用它.(特别注意)
    (3) t.isInterrupted()方法指的就是t线程的中断标记: true,或false, 它只返回结果, 不会做其他的操作.

    2. 线程状态: 阻塞中, 比如调用了sleep(), 或wait(), 或join() 阻塞方法, 此时如果t线程调用了interrupt()方法, 那么,t线程会立刻被做上标识: false变为true, 同时,
    阻塞中的t线程此时监测到自己中断标识变为了true, 便抛出了InterruptedException异常, 同时, 将t线程标记的结果重置为默认初始值: false (重点).
    接着,我们在t线程的执行方法run()中通过try--catch捕获该异常,然后手动处理结束run()方法.
  • 相关阅读:
    微博个人中心效果
    微博弹性按钮
    ios9 3dtouch 博客
    去掉导航栏阴影
    模态全屏模式,实现半透明效果
    剪切图片
    修改push动画的方向
    数据库链接池终于搞对了,直接从100ms到3ms
    如何在Java代码中去掉烦人的“!=null”
    面试官:请讲下接口具体怎么优化!
  • 原文地址:https://www.cnblogs.com/smileblogs/p/11563554.html
Copyright © 2020-2023  润新知