万隆的笔记 万隆的笔记
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
博文索引
笔试面试
  • 在线学站

    • 菜鸟教程 (opens new window)
    • 入门教程 (opens new window)
    • Coursera (opens new window)
  • 在线文档

    • w3school (opens new window)
    • Bootstrap (opens new window)
    • Vue (opens new window)
    • 阿里开发者藏经阁 (opens new window)
  • 在线工具

    • tool 工具集 (opens new window)
    • bejson 工具集 (opens new window)
    • 文档转换 (opens new window)
  • 更多在线资源
  • Changlog
  • Aboutme
GitHub (opens new window)
  • JUC介绍
  • 并发编程核心概念与主要内容
  • Java线程创建与使用
  • 线程生命周期
  • synchronized关键字
  • wait与notify
  • 线程中断-interrupt
    • isInterrupted与interrupted
    • InterruptedException
    • 轻量级阻塞与重量级阻塞
  • 线程优雅关闭
  • JMM内存模型
  • volatile关键字
  • final关键字
  • Lock
  • JUC并发编程
2022-05-06
目录

线程中断-interrupt

# 线程中断-interrupt

Thread类提供了中断线程的相关API

  • interrupt():中断线程
  • interrupted():Thread静态方法,测试当前线程是否已中断。通过该方法可以清除线程的中断状态。换句话说,如果这个方法被连续调用两次,第二个调用将返回false(除非当前线程再次被中断,在第一个调用清除其中断状态之后,在第二个调用检查它之前)。返回结果:如果当前线程已被中断,则为True;否则false。
  • isInterrupted():thread实例方法,测试此线程是否已被中断。该方法与interrupted相似,但不清除线程的清除线程的中断状态。

注意,线程中断并不是说将线程停止,而是“唤醒”,可以理解为是中断线程当前的状态,将其唤醒。

# isInterrupted与interrupted

区别:

  • interrupted()是Thread静态方法,isInterrupted()是thread实例方法。
  • interrupted()会清除线程的中断状态,可能抛异常InterruptedException,而isInterrupted()不影响线程的中断状态。

thread.interrupted()相当于给线程发送了一个唤醒的信号,所以如果线程此时恰好处于WAITING或者TIMED_WAITING状态,就会抛出一个InterruptedException,并且线程被唤醒。而如果线程此时并没有被阻塞,则线程什么都不会做。但在后续,线程可以判断自己是否收到过其他线程发来的中断信号,然后做一些对应的处理。

这两个方法都是线程用来判断自己是否收到过中断信号的,前者是实例方法,后者是静态方法。二者的区别在于,前者只是读取中断状态,不修改状态;后者不仅读取中断状态,还会重置中断标志位。

# InterruptedException

什么情况下会抛出InterruptedException?

只有那些声明了会抛出InterruptedException的函数才会抛出异常,例如sleep、wait、join:

public static native void sleep(long millis) throws InterruptedException {...} 
public final void wait() throws InterruptedException {...} 
public final void join() throws InterruptedException {...}

假设while循环中没有调用任何的阻塞函数,就是通常的算术运算,或者打印一行日志,这个时候,在主线程中调用一thread.interrupt(),该线程并不会抛出异常。如下所示:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        myThread.start();
        Thread.sleep(10);
        // 中断线程
        myThread.interrupt();
        Thread.sleep(100);

        System.exit(0);
    }
}

class MyThread extends Thread { 
  @Override public void run() { 
    while (true) { 
      boolean interrupted = isInterrupted(); 
      System.out.println("中断标记:" + interrupted); 
    } 
  } 
}

# 轻量级阻塞与重量级阻塞

能够被中断的阻塞称为轻量级阻塞,对应的线程状态是WAITING或者TIMED_WAITING;而像synchronized 这种不能被中断的阻塞称为重量级阻塞,对应的状态是 BLOCKED。

如图所示:调用不同的方法后,一个线程的状态迁移过程,状态说明见 线程生命周期

state2

初始线程处于NEW状态,调用start()开始执行后,进入RUNNING或者READY状态。如果没有调用任何的阻塞函数,线程只会在RUNNING和READY之间切换,也就是系统的时间片调度。这两种状态的切换是操作系统完成的,除非手动调用yield()函数,放弃对CPU的占用。

一旦调用了图中的任何阻塞函数,线程就会进入WAITING或者TIMED_WAITING状态,两者的区别只是前者为无限期阻塞,后者则传入了一个时间参数,阻塞一个有限的时间。如果使用了synchronized关键字或者synchronized块,则会进入BLOCKED状态。

不太常见的阻塞/唤醒函数:LockSupport.park()/unpark()。这对函数非常关键,Concurrent包中Lock的实现即依赖这一对操作原语。

因此thread.interrupted()的精确含义是“唤醒轻量级阻塞”,而不是字面意思“中断一个线程”。

上次更新: 5/30/2023, 12:05:21 AM
线程优雅关闭

线程优雅关闭→

最近更新
01
2025
01-15
02
Elasticsearch面试题
07-17
03
Elasticsearch进阶
07-16
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式