Java中线程中断停止的三种实现方法

 更新时间:2025年06月24日 09:11:10   作者:重生之Java开发工程师  
本文主要介绍了Java中线程中断停止的三种实现方法,包括stop()方法但已废弃且不安全,推荐使用volatile标志位或interrupt中断机制,具有一定的参考价值,感兴趣的可以了解一下

对于线程的停止,通常情况下我们是不会去手动去停止的,而是等待线程自然运行至结束,但在实际开发中,很多情况中需要我们提前去手动来停止线程,比如程序中出现异常错误、使用者关闭程序等情况中。如果不能很好地停止线程那么可能会导致各种问题,所以正确的停止线程是非常的重要的,常见的中断线程的方式有以下几种:

1、方式一:使用 Thread 类的 stop() 方法来终止线程(废弃):

Thread 类的 stop() 方法虽然可以终止线程,但该方法已被标识为废弃方法,原因是 stop() 方法太过暴力,即使线程只执行一半,也会被强行终止,不能保证线程资源正确释放,线程不安全,从而产生不可预料的结果,因此不提倡使用。

2、方式二:根据 volatile 修饰的标志位判断线程是否需要中断:

    public static class ChangeObjectThread extends Thread 
    {
		// 表示是否停止线程
		private volatile boolean stopMe = true;
		public void stopMe() {
			stopMe = false;
		}
 
		@Override
		public void run() {
			while (!stopMe) {
                System.out.println("I'm running");
			}
		}
	}

在上面的代码里面,定义了一个标记变量 stopMe,用于标识线程是否需要退出,当 stopMe() 方法被调用时,stopMe 就会被赋值为 false,此时在代码里面的 while(!stopMe) 就会检测到这个改动,线程就退出了

3、方式三:通过 interrupt 中断机制终止线程:

该方式的核心就是通过 interrupt() 方法设置线程的中断标志位,并通过 isInterrupt()/interrupted() 方法监视并判断中断信号,当线程检测到为 true 时则说明接收到中断信号,此时需要被中断线程做相应的处理。但如何去响应这个中断信号,被中断线程有完全的自主权,也就是中断结果是死亡或是继续运行,取决于这个被中断线程本身的逻辑。

  • Thread.interrupte():设置线程的中断标志位为 true,表示被其他线程进行了中断操作,但它不会像 stop() 方法那样强制中断正在运行的线程,仅仅起到通知被停止线程的作用;而被中断线程,则需要通过监视自身的标志位是否被中断来进行响应,比如使用 isInterrupted() 或 interrupted() 方法来判断是否被中断;
  • this.interrupted():测试当前线程是否已经中断。如果连续两次调用该方法,第一次返回 true,第二次返回false,因为 interrupted() 方法具有清除状态的功能,它内部实现是调用的当前线程的 isInterrupted(),并且会重置当前线程的中断状态。
  • this.isInterrupted():测试线程是否已经中断,但是不会清除状态标识

3.1、使用 interrupt() + isInterrupted() 来中断线程:

  public static void main(String[] args) throws InterruptedException {
     Thread thread=new Thread(()->{
         while (true){
             System.out.println("t1线程还在运行......");
             Thread current = Thread.currentThread();
             boolean interrupted = current.isInterrupted(); //默认值是false
             if (interrupted){  //如果外部调用中断 那么会将该标记改为true
                 System.out.println("接受到中断标记....."+interrupted+"开始中断线程.....");
                 current.interrupted();//再次调用interrupted测试复位标记  会重置清除标记  注意是带有ed 不是interrupt()方法
                 System.out.println("经过interrupted复位后标记为:"+current.isInterrupted());
                 break;
             }
         }

     },"t1");
    thread.start();
    thread.interrupt(); //设置线程中断
    }

//运行结果
t1线程还在运行......
接受到中断标记.....true开始中断线程.....
经过interrupted复位后标记为:false

3.2、使用 interrupt() + InterruptedException 来中断线程:

        Thread thread2=new Thread(()->{
            while (true){
                System.out.println("t2线程还在运行......");
                Thread current = Thread.currentThread();

                if (current.isInterrupted()){  //判断当前线程是否中断
                    System.out.println("接受到中断标记....."+Thread.currentThread().isInterrupted());
                  //  break;
                }
                try {
                    TimeUnit.SECONDS.sleep(5); //5s睡眠
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    //因为抛出异常后会将线程标记恢复为 默认值false
                    System.out.println("Thread.currentThread().isInterrupted() = " + Thread.currentThread().isInterrupted());
                    break;
                }
            }

        },"t2");
        thread2.start();
        thread2.interrupt();
    }

t2线程还在运行......
接受到中断标记.....true
Thread.currentThread().isInterrupted() = false
java.lang.InterruptedException: sleep interrupted
	at java.base/java.lang.Thread.sleep(Native Method)
	at java.base/java.lang.Thread.sleep(Thread.java:339)
	at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446)
	at com.java.thread.TestInterrupt.lambda$main$0(TestInterrupt.java:40)
	at java.base/java.lang.Thread.run(Thread.java:834)

从上面的执行结果可以证明,当线程处于阻塞状态(Sleep、wait、join)时,也是可以感受到中断通知并抛出异常的,所以不用担心长时间休眠中线程感受不到中断了。

对于线程的停止,最正确最优雅的方式就是通过 interrupt() 的方式来实现,但 interrupt() 仅起到通知被停止线程的作用,对被停止的线程而言,它拥有完全的自主权,既可以立即停止,也可以选择一段时间后停止,也可以选择不停止。比如抛出 InterruptedException 后,再次中断设置,让程序能后续继续进行终止操作;也比如线程在进行 IO 操作时,比如写文件操作,这时接收到终止线程的信号,那么它不会立马停止,而是根据自身业务来判断该如何处理,是将整个文件写入成功后再停止还是不停止都取决于被通知线程的处理,因为如果立马终止线程就可能造成数据的不完整性,这并不是业务所不希望的结果。那么可能很多读者会疑惑,既然这样那存在的意义有什么呢,其实是因为对于 Java 而言,就是期望程序之间是能够相互通知、协作的管理线程

到此这篇关于Java中线程中断停止的三种实现方法的文章就介绍到这了,更多相关Java 线程中断停止内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java调用Python脚本传递数据并返回计算结果

    Java调用Python脚本传递数据并返回计算结果

    实际工程项目中可能会用到Java和python两种语言结合进行,这样就会涉及到一个问题,Java如何调用Python脚本,感兴趣的可以了解一下
    2021-05-05
  • 使用Java增删改查数据库的操作方法

    使用Java增删改查数据库的操作方法

    这篇文章主要介绍了使用Java增删改查数据库的操作方法,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-12-12
  • java代码获取jenkins数据,构建历史等信息方式

    java代码获取jenkins数据,构建历史等信息方式

    这篇文章主要介绍了java代码获取jenkins数据,构建历史等信息方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • 如何在springboot中使用定时任务

    如何在springboot中使用定时任务

    这篇文章主要介绍了如何在springboot中使用定时任务,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下
    2020-12-12
  • javaweb图书商城设计之用户模块(1)

    javaweb图书商城设计之用户模块(1)

    这篇文章主要介绍了javaweb图书商城设计之用户模块的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • Springboot静态资源的访问方法介绍

    Springboot静态资源的访问方法介绍

    最近在做SpringBoot项目的时候遇到了“白页”问题,通过查资料对SpringBoot访问静态资源做了总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • IDEA中的HTTP Client使用教程

    IDEA中的HTTP Client使用教程

    这篇文章主要介绍了IDEA中的HTTP Client使用教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java两种动态代理JDK动态代理和CGLIB动态代理详解

    Java两种动态代理JDK动态代理和CGLIB动态代理详解

    这篇文章主要介绍了Java两种动态代理JDK动态代理和CGLIB动态代理详解,代理模式是23种设计模式的一种,他是指一个对象A通过持有另一个对象B,可以具有B同样的行为的模式,为了对外开放协议,B往往实现了一个接口,A也会去实现接口,需要的朋友可以参考下
    2023-11-11
  • Java流程控制顺序结构原理解析

    Java流程控制顺序结构原理解析

    这篇文章主要介绍了Java流程控制顺序结构原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • SpringBoot 单元测试JUnit的使用详解

    SpringBoot 单元测试JUnit的使用详解

    这篇文章主要介绍了SpringBoot 单元测试JUnit的使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11

最新评论