当前位置: 代码迷 >> 综合 >> Thread类方法之二--interrupt
  详细解决方案

Thread类方法之二--interrupt

热度:87   发布时间:2024-01-10 06:21:28.0

interrupt 方法打断线程

  • case1:打断sleep, wait, join (阻塞)的线程
  • case2:打断运行中的线程

打断阻塞状态中的线程,会抛出一个InterruptedException异常,并且会重置打断标记

  • 介绍一下打断标记

Thread类里有一个isInterrupted方法可以返回当前线程是否被打断,被打断返回true,否则false

public boolean isInterrupted() {
    return isInterrupted(false); // 这里的false指不会重置打断标记}

还有一个类似的静态方法interrupted也可以返回当前线程是否被打断,被打断返回true,否则false,但是会重置打断标记为false。

    public static boolean interrupted() {
    return currentThread().isInterrupted(true);  // 这里的true指会重置打断标记}
打断阻塞状态的线程
public class Test {
    public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
    log.debug("sleep...");try {
    Thread.sleep(5000); // wait, join} catch (InterruptedException e) {
    e.printStackTrace();}},"t1");t1.start();Thread.sleep(1000);log.debug("interrupt");log.debug("打断标记:{}", t1.isInterrupted()); // 1t1.interrupt();log.debug("打断标记:{}", t1.isInterrupted()); // 2}
}/*Output: 22:29:08.624 c.Test11 [t1] - sleep... 22:29:09.621 c.Test11 [main] - interrupt 22:29:09.621 c.Test11 [main] - 打断标记:false 22:29:09.624 c.Test11 [main] - 打断标记:false java.lang.InterruptedException: sleep interruptedat java.lang.Thread.sleep(Native Method)at cn.itcast.test.Test11.lambda$main$0(Test11.java:12)at java.lang.Thread.run(Thread.java:748) */

上面两个false是意义不同的,第一个代表当前线程正常运行,没有被打断;而第二个false代表线程在sleep, wait, join 中(阻塞状态)被打断,会抛出异常并将打断标记重置为false。

打断正常运行的线程
public class Test {
    public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
    while(true) {
    System.out.println("isInterrupted状态: " + (Thread.currentThread().isInterrupted()));}}, "t1");t1.start();Thread.sleep(1000);log.debug("interrupt");t1.interrupt();}
}/*Output: ... isInterrupted状态: false isInterrupted状态: false isInterrupted状态: false 22:43:30.383 c.Test12 [main] - interrupt isInterrupted状态: true isInterrupted状态: true isInterrupted状态: true ... 

打断后标记变为true, 但是进程并没有停止,那么这个打断到底有啥用啊?我们怎么让被打断后的进程停下来哪?我们可以借助打断标记,如果打断标记为真,就手动退出进程。

public class Test {
    public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
    while(true) {
    boolean interrupted = Thread.currentThread().isInterrupted();if(interrupted) {
    log.debug("被打断了, 退出循环");break;}}}, "t1");t1.start();Thread.sleep(1000);log.debug("interrupt");t1.interrupt();}
}/*Output: 22:52:17.742 c.Test12 [main] - interrupt 22:52:17.747 c.Test12 [t1] - 被打断了, 退出循环 */

interrupt应用:多线程设计模式之两阶段终止

Two Phase Termination :在一个线程 T1 中如何“优雅”终止线程 T2?这里的【优雅】指的是给 T2 一个料理后事的机会。

错误思路
  • 使用线程对象的 stop() 方法停止线程
    • stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁, 其它线程将永远无法获取锁
  • 使用 System.exit(int) 方法停止线程
    • 目的仅是停止一个线程,但这种做法会让整个程序都停止
两阶段终止模式
  • 应用场景:后台监控线程(需要设置停止选项)
  • 思路
    在这里插入图片描述
@Slf4j(topic = "c.TwoPhaseTermination")
public class Test_1 {
    public static void main(String[] args) throws InterruptedException {
    TwoPhaseTermination_1 tpt = new TwoPhaseTermination_1();tpt.start();Thread.sleep(3500);log.debug("停止监控");tpt.stop();}
}@Slf4j(topic = "c.TwoPhaseTermination")
class TwoPhaseTermination_1 {
    // 监控线程private Thread monitorThread;// 启动监控线程public void start() {
    monitorThread = new Thread(() -> {
    while (true) {
    Thread current = Thread.currentThread();// 是否被打断if (current.isInterrupted()) {
    log.debug("料理后事");break;}try {
    Thread.sleep(1000);          // 睡眠时被打断log.debug("执行监控记录");   // 正常打断} catch (InterruptedException e) {
    e.printStackTrace();// 当抛出异常时,重新设置打断标记current.interrupt();}}}, "monitor");monitorThread.start();}// 停止监控线程public void stop() {
    monitorThread.interrupt();}
}/*Output: 00:30:54.263 c.TwoPhaseTermination [monitor] - 执行监控记录 00:30:55.263 c.TwoPhaseTermination [monitor] - 执行监控记录 00:30:56.265 c.TwoPhaseTermination [monitor] - 执行监控记录 00:30:56.765 c.TwoPhaseTermination [main] - 停止监控 00:30:56.765 c.TwoPhaseTermination [monitor] - 料理后事 java.lang.InterruptedException: sleep interruptedat java.lang.Thread.sleep(Native Method)at cn.itcast.test.TwoPhaseTermination_1.lambda$start$0(Test_1.java:33)at java.lang.Thread.run(Thread.java:748) */

在睡眠时被打断,抛出异常并优雅的退出线程。正常运行时被打断,优雅的退出线程。

  相关解决方案