• 【线程中断】什么是中断、interrupt、isInterrupted、interrupted⽅法源码解析、如何使⽤中断标识停⽌线程_JUC18


    1、什么是中断

    • 1.在Java中没有办法⽴即停⽌⼀条线程,然⽽停⽌线程却显得尤为重要,如取消⼀个耗时操作。因此,Java提供了⼀种⽤于停⽌线程的机制 — 中断
    • 2.若要中断⼀个线程,你需要⼿动调⽤该线程的interrupt⽅法,该⽅法也仅仅是将线程对象的中断标识设为true
    • 3.每个线程对象中都有⼀个标识,⽤于标识线程是否被中断;该标识位为true表示中断,为false表示未中断;通过调⽤线程对象的interrupt⽅法将线程的标识位设为true;可以在别的线程中调⽤,也可以在⾃⼰的线程中调⽤。

    2、源码解读(中断的相关API)

    1)void interrupt( )实例⽅法
    • 1.概述:interrupt( )仅仅是设置线程的中断状态为true不会停⽌线程
    • 2.**源码解读:**如果这个线程wait()、join()、sleep()⽅法在⽤的过程中调用interupt(),会抛出Interrupte dException

    在这里插入图片描述

    2)boolean isInterrupted( )实例⽅法
    • 概念:判断当前线程是否被中断(通过检查中断标识位) (属于实例⽅法)。

    在这里插入图片描述

    3)static boolean interrupted( )静态⽅法
    • 判断线程是否被中断并清除当前中断状态,这个⽅法做了两件事返回当前线程的中断状态 &将当前线程的中断状态设为false
    • 原理:假设有两个线程A、B,线程B调⽤了interrupt⽅法,这个时候我们连续调⽤两次interrupted⽅法第⼀次会返回true并将中断标识位设置位false,所以第⼆次调⽤将返回false
    4)⽐较静态⽅法interrupted和实例⽅法isInterrupted
    • 1.静态⽅法interrupted将会清除中断状态,清除之后就是默认的false(不中断)(传⼊的参数ClearInterrupted为true)
    • 2.实例⽅法isInterrupted则不会(传⼊的参数ClearInterrupted为false)

    在这里插入图片描述


    3、如何使⽤中断标识停⽌线程

    • ①. 在需要中断的线程中不断监听中断状态,一旦发生中断,就执行型对于的中断处理业务逻辑。
    • ②. 三种中断标识停止线程的方式:
      • 方式1:通过⼀个volatile变量实现
      • 方式2:通过AtomicBoolean
      • 方式3:通过Thread类⾃带的中断API⽅法实现。
    public class InterruptDemo{
        static volatile boolean isStop = false;//方式1
        static AtomicBoolean atomicBoolean = new AtomicBoolean(false);//方式2
        
        /**
         * 方式1:通过一个volatile变量实现
         */
        public static void m1(){
            new Thread(() -> {
                while(true)
                {
                    //通过监听中断标识自己结束线程(结束逻辑程序员自定义)
                    if(isStop)
                    {
                        System.out.println("-----isStop = true,程序结束。");
                        break;
                    }
                    System.out.println("------hello isStop");
                }
            },"t1").start();
    
            //暂停几秒钟线程
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
    
            //其他线程修改中断表示
            new Thread(() -> {
                isStop = true;
            },"t2").start();
        }
        
        /**
         * 方式2:通过AtomicBoolean
         */
        public static void m2(){
            new Thread(() -> {
                while(true)
                {
                    //通过监听中断标识自己结束线程(结束逻辑程序员自定义)
                    if(atomicBoolean.get())
                    {
                        System.out.println("-----atomicBoolean.get() = true,程序结束。");
                        break;
                    }
                    System.out.println("------hello atomicBoolean");
                }
            },"t1").start();
    
            //暂停几秒钟线程
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
    
            //其他线程修改中断表示
            new Thread(() -> {
                atomicBoolean.set(true);
            },"t2").start();
        }
        
        /**
         * 方式3:Thread类⾃带的中断API⽅法interrupt()
         */
        public static void m3(){
            
            Thread t1 = new Thread(() -> {
                while (true) {
                    //通过监听中断标识自己结束线程(结束逻辑程序员自定义)
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("-----isInterrupted() = true,程序结束。");
                        break;
                    }
                    System.out.println("------hello Interrupt");
                }
            }, "t1");
            t1.start();
    
        	
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
    
            //其他线程修改中断表示
            new Thread(() -> {
                t1.interrupt();//修改t1线程的中断标志位为true
            },"t2").start();
    	}
    }
    
    • 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

    4、当前线程的中断标识为true,是不是就⽴刻停⽌?

    • 1.线程调⽤interrupt()时:

      • ①. 如果线程处于正常活动状态,那么会将线程的中断标志设置位true仅此⽽已。被设置中断标志的线程将继续正常运⾏,不受影响。所以,interrupt( )并不能真正的中断线程,需要被调⽤的线程⾃⼰进⾏配合才⾏
      • ②. 如果线程处于被阻塞状态(例如处于sleep、wait、join等状态),在别的线程中调⽤当前线程对象的interrupt⽅法,那么线程⽴即被阻塞状态,并抛出⼀个InterruptedException异常
    • 2.中断只是⼀种协同机制修改中断标识位仅此⽽已,不是⽴即stop打断。

    • 3.sleep⽅法抛出InterruptedException后中断标识也被清空置为false。如果我们在catch没有通过调用th.interrupt( )方法再次将中断标识位设置位true,这就是导致无限循环了。

        public static void m5()
        {
            Thread t1 = new Thread(() -> {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("-----isInterrupted() = true,程序结束。");
                        break;
                    }
                    
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        //线程的中断标志位重新设置为false,无法停下,需要再次掉interrupt()设置true
                        Thread.currentThread().interrupt();//???????
                        e.printStackTrace();
                    }
                    
                    System.out.println("------hello Interrupt");
                }
            }, "t1");
            t1.start();
    
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
    
            //其他线程修改中断表示
            new Thread(() -> {
                t1.interrupt();//修改t1线程的中断标志位为true
            },"t2").start();
        }
    
    • 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

  • 相关阅读:
    Flutter高仿微信-第57篇-添加好友
    MySQL之分库分表
    C++ --- Day05
    java面试题
    idea热部署Jrebel插件和自动手动三种方式实现
    02【SpringMVC的工作流程】
    CMS与FullGC
    『现学现忘』Git基础 — 13、Git的基础操作
    JavaWeb实现登录注册功能[代码+详解]
    加法器:如何像搭乐高一样搭电路(上)?
  • 原文地址:https://blog.csdn.net/weixin_38963649/article/details/126144505