Java线程中断机制interrupt、isInterrupted、interrupted方法详解

 更新时间:2024年01月22日 09:01:48   作者:帅气的喵喵  
这篇文章主要介绍了Java线程中断机制interrupt、isInterrupted、interrupted方法详解,一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,所以,Thread.stop、Thread.suspend、Thread. resume都已经被废弃了,需要的朋友可以参考下

什么是中断

  • 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,所以,Thread.stop、Thread.suspend、Thread. resume都已经被废弃了
  • 在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。因此,Java提供了一种用于停止线程的机制 — 中断
  • 中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现
  • 若要中断一个线程,你需要手动调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设为true
  • 每个线程对象中都有一个标识,用于标识线程是否被中断;该标识位为true表示中断,为false表示未中断,通过调用线程对象的interrupt方法将线程的标识位设为true,可以在别的线程中调用,也可以在自己的线程中调用

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

void interrupt( )实例方法

 interrupt( )仅仅是设置线程的中断状态为true,不会停止线程

源码解读(如果这个线程因为wait()、join()、sleep()方法在用的过程中被打断(interupt),会抛出Interrupte dException)

boolean isInterrupted( )实例方法

判断当前线程是否被中断(通过检查中断标识位) 实例方法

在这里插入图片描述

static boolean interrupted( )静态方法

 判断线程是否被中断,并清楚当前中断状态,这个方法做了两件事 第一件事 返回当前线程的中断状态

 第二件事 将当前线程的中断状态设为false

原理:假设有两个线程A、B,线程B调用了interrupt方法,这个时候我们连续调用两次isInterrupted方法,第一次会返回true,然后这个方法会将中断标识位设置位false,所以第二次调用将返回false

在这里插入图片描述

比较静态方法interrupted和实例方法isInterrupted 静态方法interrupted将会清除中断状态(传入的参数ClearInterrupted位true)实例方法isInterrupted则不会(传入的参数ClearInterrupted为false)

如何使用中断标识停止线程

在需要中断的线程中不断监听中断状态,一旦发生中断,就执行型对于的中断处理业务逻辑

三种中断标识停止线程的方式

  • 通过一个volatile变量实现
  • 通过AtomicBoolean
  • 通过Thread类自带的中断API方法实现
public class InterruptDemo{
    static volatile boolean isStop = false;
    static AtomicBoolean atomicBoolean = new AtomicBoolean(false);
    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();
}
    /**
     * 通过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();
    }
    /**
     * 通过一个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();
    }
}

当前线程的中断标识为true,是不是就立刻停止?

1、线程调用interrupt()时①. 如果线程处于正常活动状态,那么会将线程的中断标志设置位true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。所以,interrupt( )并不能真正的中断线程,需要被调用的线程自己进行配合才行

如果线程处于被阻塞状态(例如处于sleep、wait、join等状态),在别的线程中调用当前线程对象的interrupt方法,那么线程立即被阻塞状态,并抛出一个InterruptedException异常)

2、中断只是一种协同机制,修改中断标识位仅此而已,不是立即stop打断

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

总结

package com.bilibili.juc.interrupt;
import java.util.concurrent.TimeUnit;
/**
 * @auther zzyy
 * @create 2022-01-20 10:52
 */
public class InterruptDemo3
{
    public static void main(String[] args)
    {
        Thread t1 = new Thread(() -> {
            while (true)
            {
                if(Thread.currentThread().isInterrupted())
                {
                    System.out.println(Thread.currentThread().getName()+"\t " +
                            "中断标志位:"+Thread.currentThread().isInterrupted()+" 程序停止");
                    break;
                }
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();//为什么要在异常处,再调用一次??
                    e.printStackTrace();
                }
                System.out.println("-----hello InterruptDemo3");
            }
        }, "t1");
        t1.start();
        //暂停几秒钟线程
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
        new Thread(() -> t1.interrupt(),"t2").start();
    }
}
/**
 * 1 中断标志位,默认false
 * 2 t2 ----> t1发出了中断协商,t2调用t1.interrupt(),中断标志位true
 * 3 中断标志位true,正常情况,程序停止,^_^
 * 4 中断标志位true,异常情况, 就是t1过程中调用了sleep 、join 、 wait 方法 会抛出一个 InterruptedException(中断异常),
 * 将会把中断状态将被清除,并且将收到InterruptedException 。中断标志位重新设置为false 导致无限循环
 *
 * 5 所以如果要线程中调用sleep 、join 、 wait 方法 需要在catch块中,需要再次给中断标志位设置为true,2次调用停止程序才OK
 */

到此这篇关于Java线程中断机制interrupt、isInterrupted、interrupted方法详解的文章就介绍到这了,更多相关Java线程中断机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 单例模式的反射漏洞和反序列化漏洞代码实例

    单例模式的反射漏洞和反序列化漏洞代码实例

    这篇文章主要介绍了单例模式的反射漏洞和反序列化漏洞,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • 浅谈java中为什么实体类需要实现序列化

    浅谈java中为什么实体类需要实现序列化

    下面小编就为大家带来一篇浅谈java中为什么实体类需要实现序列化。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • Java设计模式之GOF23全面讲解

    Java设计模式之GOF23全面讲解

    这篇文章主要介绍了Java设计模式之GOF23全面讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • PL/SQL实现JAVA中的split()方法的例子

    PL/SQL实现JAVA中的split()方法的例子

    这篇文章主要介绍了PL/SQL实现JAVA中的split()方法的例子的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-07-07
  • MyBatis-Plus批量操作SQL日志不打印问题的解决方案

    MyBatis-Plus批量操作SQL日志不打印问题的解决方案

    在使用 MyBatis-Plus 的 saveBatch() 和 updateBatchById() 方法进行批量数据操作时,发现自定义的 Druid SQL 日志拦截器无法打印这些批量操作的 SQL 语句,导致调试和问题排查困难,本文给大家该问题的详细解决方案,需要的朋友可以参考下
    2026-03-03
  • Java的绘图模式使用浅析

    Java的绘图模式使用浅析

    这篇文章主要介绍了Java的绘图模式使用浅析,以一个小例子大概列举了XOR模式下能干的一些事情,需要的朋友可以参考下
    2015-10-10
  • SpringBoot整合MybatisPlus的基本应用指南

    SpringBoot整合MybatisPlus的基本应用指南

    MyBatis-Plus ,简称 MP,是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,下面小编就来和大家介绍一下SpringBoot整合MybatisPlus的一些基本应用吧
    2025-03-03
  • springboot3.0整合rabbitmq3.13的实现示例

    springboot3.0整合rabbitmq3.13的实现示例

    本文主要介绍了springboot3.0整合rabbitmq3.13的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09
  • Java 链表实战真题训练

    Java 链表实战真题训练

    跟着思路走,之后从简单题入手,反复去看,做过之后可能会忘记,之后再做一次,记不住就反复做,反复寻求思路和规律,慢慢积累就会发现质的变化
    2022-04-04
  • Spring Boot Aop执行顺序深入探究

    Spring Boot Aop执行顺序深入探究

    这篇文章主要为大家介绍了Spring Boot Aop执行顺序深入探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01

最新评论