线程中断方法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;
}
目录
相关文章
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
32 3
|
2月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
25 2
|
2月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
25 1
|
2月前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
47 1
|
2月前
|
Java
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅。它们用于线程间通信,使线程能够协作完成任务。通过这些方法,生产者和消费者线程可以高效地管理共享资源,确保程序的有序运行。正确使用这些方法需要遵循同步规则,避免虚假唤醒等问题。示例代码展示了如何在生产者-消费者模型中使用`wait()`和`notify()`。
32 1
|
2月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
53 1
|
2月前
|
Java
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件成立时被唤醒,从而有效解决数据一致性和同步问题。本文通过对比其他通信机制,展示了 `wait()` 和 `notify()` 的优势,并通过生产者-消费者模型的示例代码,详细说明了其使用方法和重要性。
41 1
|
2月前
|
监控 Java
在实际应用中选择线程异常捕获方法的考量
【10月更文挑战第15天】选择最适合的线程异常捕获方法需要综合考虑多种因素。没有一种方法是绝对最优的,需要根据具体情况进行权衡和选择。在实际应用中,还需要不断地实践和总结经验,以提高异常处理的效果和程序的稳定性。
30 3
|
2月前
|
监控 Java
捕获线程执行异常的多种方法
【10月更文挑战第15天】捕获线程执行异常的方法多种多样,每种方法都有其特点和适用场景。在实际开发中,需要根据具体情况选择合适的方法或结合多种方法来实现全面有效的线程异常捕获。这有助于提高程序的健壮性和稳定性,减少因线程异常带来的潜在风险。
30 1