Skip to content

Java线程中断机制

ZhangPan edited this page Jul 13, 2025 · 7 revisions

为什么不建议使用stop方法终止线程?

  1. 数据不一致风险​
  • stop方法会立即释放线程持有的所有锁,可能导致被保护的数据处于不一致状态
  • 示例:线程在更新共享资源时被强制停止,其他线程可能读取到部分更新的数据

​2. 资源泄漏问题​

  • 线程被强制终止时,可能无法执行finally块中的资源释放代码
  • 文件描述符、数据库连接等系统资源可能无法正确关闭

​3. 不可预测的行为​

  • stop方法会抛出ThreadDeath异常,这个异常通常不可被捕获
  • 可能导致程序出现难以调试的异常行为

​4. 官方废弃状态​

  • 从Java 1.2开始被标记为@Deprecated
  • 在Java 9及以后版本中已被完全移除

如何优雅的终止线程

Java线程中断机制是一种协作式的线程通信机制,它允许一个线程通知另一个线程应该停止当前操作或改变行为,但不会强制终止目标线程的执行。

每个Java线程内部都有一个boolean类型的中断状态标志位,默认为false。调用interrupt()方法会将该标志位设置为true。

线程中断相关的方法有:

  • 1、java.lang.Thread#interrupt

中断目标线程,给目标线程发一个中断信号,线程被打上中断标记。

  • 2.java.lang.Thread#isInterrupted()

判断目标线程是否被中断,不会清除中断标记。

  • 3.java.lang.Thread#interrupted Thread中的一个静态方法,判断目标线程是否被中断,如果是被标记了中断状态,会清除中断标记。

interrupt方法中断线程仅仅是设置了一个中断标记,如果在线程run方法中不去相应中断,则中断标记不会对线程产生任何影响。

如下代码,thread线程并不会被中断

    public static void testInterrupt() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("thread " + Thread.currentThread().getName() + " is running");
                }
            }
        });
        thread.start();
        thread.interrupt();
    }

如果要中断线程,则需要判断interrupt标记位,然后结束线程

    public static void testInterrupt() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("thread " + Thread.currentThread().getName() + " is interrupted");
                        return;
                    }
                    System.out.println("thread " + Thread.currentThread().getName() + " is running");
                }
            }
        });
        thread.start();
        thread.interrupt();
    }
  • 当让线程进入休眠状态后,中断标记失效,如下示例:
 public static void testInterrupt2() throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("thread " + Thread.currentThread().getName() + " is interrupted");
                        return;
                    }
                    System.out.println("thread " + Thread.currentThread().getName() + " is running");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
    }

输出结果如下:

thread Thread-0 is running
java.lang.InterruptedException: sleep interrupted
	at java.base/java.lang.Thread.sleep(Native Method)
	at thread.InterruptDemo$2.run(InterruptDemo.java:33)
	at java.base/java.lang.Thread.run(Thread.java:834)
thread Thread-0 is running
thread Thread-0 is running
thread Thread-0 is running
thread Thread-0 is running
thread Thread-0 is running
thread Thread-0 is running
thread Thread-0 is running
thread Thread-0 is running
...

可以看到线程抛出了一个中断异常,之后线程仍然在执行。

当线程在调用wait()、sleep()或join()等阻塞方法时被中断,会抛出InterruptedException异常。同时,​中断标志位会被清除​(重置为false)。线程会继续运行。如果需要打断sleep状态的线程,需要捕获 InterruptedException 异常后再次调用interrupt方法。如下:

  public static void testInterrupt2() throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("thread " + Thread.currentThread().getName() + " is interrupted");
                        return;
                    }
                    System.out.println("thread " + Thread.currentThread().getName() + " is running");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        Thread.currentThread().interrupt();
                    }
                }
            }
        });
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
    }

输出结果如下:

thread Thread-0 is running
java.lang.InterruptedException: sleep interrupted
	at java.base/java.lang.Thread.sleep(Native Method)
	at thread.InterruptDemo$2.run(InterruptDemo.java:33)
	at java.base/java.lang.Thread.run(Thread.java:834)
thread Thread-0 is interrupted

Java采用这种协作式中断机制而非强制终止,主要为了避免

  • 资源泄漏(如未释放的锁、未关闭的文件)
  • 数据不一致(如只完成部分数据更新)
  • 死锁风险(如suspend()可能导致)

这种机制将如何响应中断的决定权交给被中断线程本身,使其有机会进行必要的清理工作,实现"优雅停止"

公众号:玩转安卓Dev

Java基础

面向对象与Java基础知识

Java集合框架

JVM

多线程与并发

设计模式

Kotlin

Android

项目相关问题

Android基础知识

Android消息机制

Android Binder

View事件分发机制

Android屏幕刷新机制

View的绘制流程

Activity启动

Framework

性能优化

Jetpack&系统View

第三方框架实现原理

计算机网络

算法

Clone this wiki locally