线程中断方法interrupt、isInterrupted、interrupted方法

简介: 线程中断方法interrupt、isInterrupted、interrupted方法

微信截图_20230224215627.png


Thread.currentThread().interrupt()


该方法为非静态方法,该方法的作用:标记线程为中断状态,仅仅是标记


/**
 * @author chaird
 * @create 2020-12-22 13:58
 */
public class Main {
  public static void main(String[] args) {
    // 获取当前线程
    Thread currentThread = Thread.currentThread();
    // 获取当前线程的中断状态
    System.out.println(currentThread.isInterrupted()); // false
    // 标记为中断线程
    currentThread.interrupt();
    // 获取当前线程的中断状态
    System.out.println(currentThread.isInterrupted()); // true
  }
}


Thread.currentThread().isInterrupted()


该方法为非静态方法,该方法的作用:返回线程的中断状态


/**
 * @author chaird
 * @create 2020-12-22 13:58
 */
public class Main {
  public static void main(String[] args) {
    // 获取当前线程
    Thread currentThread = Thread.currentThread();
    // 获取当前线程的中断状态
    System.out.println(currentThread.isInterrupted()); // false
    // 标记为中断线程
    currentThread.interrupt();
    // 获取当前线程的中断状态
    System.out.println(currentThread.isInterrupted()); // false
  }
}


Thread.interrupted()


/**
 * @author chaird
 * @create 2020-12-22 13:58
 */
public class Main {
  public static void main(String[] args) {
    // 获取当前线程
    Thread currentThread = Thread.currentThread();
    // 获取当前线程的中断状态
    System.out.println(currentThread.isInterrupted()); // false
    // 标记为中断线程
    currentThread.interrupt();
    // 获取当前线程的中断状态
    System.out.println(currentThread.isInterrupted()); // false
    // (1)获取当前线程的中断状态,(2)并且取消中断状态
    boolean interrupted = Thread.interrupted();
    System.out.println(interrupted); // true
    System.out.println(currentThread.isInterrupted()); // false 。因为Thread.interrupted()中取消中断状态
  }
}


如何正确的中断一个正在执行的线程


案例1:没有坑并且不带Sleep的代码


import java.time.LocalDateTime;
/**
 * @author chaird
 * @create 2020-12-22 14:15
 */
public class Start {
  public static void main(String[] args) {
    InterruptedTask interruptedTask = new InterruptedTask();
    Thread interruptedThread = new Thread(interruptedTask);
    interruptedThread.start();
    try {
      // 睡1秒
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    // 设置线程为中断状态
    interruptedThread.interrupt();
  }
}
class InterruptedTask implements Runnable {
  @Override
  public void run() {
    Thread currentThread = Thread.currentThread();
    while (true) {
      if (currentThread.isInterrupted()) {
        break;
      }
      System.out.println("LocalDateTime:" + LocalDateTime.now().toString());
    }
  }
}


案例2:有坑并且带Sleep的代码


下述代码明明调用了线程的interrupt()方法来中断线程,但是却并没有起到啥作用。原因是线程的run()方法在执行的时候,大部分时间都是阻塞在sleep(100)上,当其他线程通过调用执行线程的interrupt()方法来中断执行线程时,大概率的会触发InterruptedException异常,在触发InterruptedException异常的同时,JVM会同时把线程的中断标志位清除,所以,这个时候在run()方法中判断的currentThread.isInterrupted()会返回false,也就不会退出当前while循环了。


import java.time.LocalDateTime;
/**
 * @author chaird
 * @create 2020-12-22 14:15
 */
public class Start {
  public static void main(String[] args) {
    InterruptedTask interruptedTask = new InterruptedTask();
    Thread interruptedThread = new Thread(interruptedTask);
    interruptedThread.start();
    try {
      // 睡1秒
      Thread.sleep(500);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    // 设置线程为中断状态
    interruptedThread.interrupt();
  }
}
class InterruptedTask implements Runnable {
  @Override
  public void run() {
    Thread currentThread = Thread.currentThread();
    while (true) {
      if (currentThread.isInterrupted()) {
        break;
      }
      System.out.println("LocalDateTime:" + LocalDateTime.now().toString());
      try {
        // 睡0.1秒
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}


解决办法


import java.time.LocalDateTime;
/**
 * @author chaird
 * @create 2020-12-22 14:15
 */
public class Start {
  public static void main(String[] args) {
    InterruptedTask interruptedTask = new InterruptedTask();
    Thread interruptedThread = new Thread(interruptedTask);
    interruptedThread.start();
    try {
      // 睡1秒
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    // 设置线程为中断状态
    interruptedThread.interrupt();
  }
}
class InterruptedTask implements Runnable {
  @Override
  public void run() {
    Thread currentThread = Thread.currentThread();
    while (true) {
      if (currentThread.isInterrupted()) {
        break;
      }
      System.out.println("LocalDateTime:" + LocalDateTime.now().toString());
      try {
        // 睡0.1秒
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
        // 在触发InterruptedException异常的同时,JVM会同时把线程的中断标志位清除,所以需要复现中断状态
        currentThread.interrupt();
      }
    }
  }
}


案例3:有坑,需要JMM知识解决


主线程睡0.5秒,然后去中断interruptedThread线程,但是运行下面的代码线程并没有结束,说明有BUG


/**
 * @author chaird
 * @create 2020-12-22 14:15
 */
public class Start {
  public static void main(String[] args) {
    InterruptedTask interruptedTask = new InterruptedTask();
    Thread interruptedThread = new Thread(interruptedTask);
    interruptedThread.start();
    try {
      // 睡0.5秒
      Thread.sleep(500);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    interruptedTask.myInterrupted();
  }
}
class InterruptedTask implements Runnable {
  private boolean sign = false;
  @Override
  public void run() {
    Thread currentThread = Thread.currentThread();
    while (!sign) {}
  }
  public void myInterrupted() {
    sign = true;
  }
}


解决办法


因为InterruptedTask里的while(true)太快了,没有任何逻辑,所以一个字:快。


虽然JMM中主内存中的更新了数据,但是本地内存来不及去主内存中更新数据,所以上面的案例中InterruptedTask里的sign一直都是false。volatile可以解决内存可见性。这就是另一个知识点了,不多解释。


private boolean sign = false
改为
private volatile boolean sign = false;


注意


本文中说的中断状态其实就是一个标志位,而不是真正的中断线程


class MyThread {
  // 中断状态标志位
  private volatile boolean sign = false;
}
目录
相关文章
|
1月前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结
|
1月前
|
Java 测试技术
血的教训--如何正确使用线程池submit和execute方法
血的教训--如何正确使用线程池submit和execute方法
26 1
|
1月前
|
Java API 调度
线程的中断(interrupt)机制
线程的中断(interrupt)机制
30 1
|
2月前
|
人工智能 Java API
Python 潮流周刊#28:两种线程池、四种优化程序的方法
Python 潮流周刊#28:两种线程池、四种优化程序的方法
23 1
|
3月前
|
监控 Java 应用服务中间件
剑指JUC原理-3.线程常用方法及状态(下)
剑指JUC原理-3.线程常用方法及状态
59 0
|
3月前
|
安全 Java Kotlin
面试必备:Kotlin 线程同步的 N 种方法
面试必备:Kotlin 线程同步的 N 种方法
83 0
|
4月前
|
Java
学习多线程之yield方法
学习多线程之yield方法
45 0
|
5月前
|
监控 安全 算法
Thread入门与线程方法详解及多线程安全
Thread入门与线程方法详解及多线程安全
21 0
|
9天前
使用代理IP池实现多线程的方法
使用代理IP池实现多线程的方法
|
29天前
|
Java 测试技术 Python
Python开启线程和线程池的方法
Python开启线程和线程池的方法
17 0
Python开启线程和线程池的方法