多线程-中断

1. 核心

  1. 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止
  2. 在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作
  3. 中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要自己实现
  • 若要中断一个线程,你需要手动调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设成true 接着你需要自己写代码不断地检测当前线程的标识位,如果为true,表示别的线程要求这条线程中断, 此时究竟该做什么需要你自己写代码实现。
    • 每个线程对象中都有一个标识,用于表示线程是否被中断;该标识位为true表示中断,为false表示未中断; 通过调用线程对象的inter

2. API

2.1. interrupt()

实例方法interrupt()仅仅是设置线程的中断状态为true,不会停止线程

2.2. static boolean interrupted()

Thread.interrupted(); 判断线程是否被中断,并清除当前中断状态

返回当前线程的中断状态

将当前线程的中断状态设为false

System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted()); //false
System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted()); //false
System.out.println("111111");
Thread.currentThread().interrupt();///----false---> true
System.out.println("222222");
System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted()); //true
System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted());//false

2.3. boolean isInterrupted()

实例方法,判断当前线程是否被中断(通过检查中断标志位) 默认false

3. 中断标识停止线程

在需要中断的线程中不断监听中断状态,一旦发生中断,就执行相应的中断处理业务逻辑

3.1. 通过一个volatile变量实现

public class InterruptDemo {
  static volatile boolean isStop = false;
  public static void main(String[] args) {
    m1();
  }
  public static void m1() {
    new Thread(() -> {
      while (true) {
        if (isStop) {
          System.out.println("-----isStop = true,程序结束。");
          break;
        }
        System.out.println("------hello isStop");
      }
    }, "t1").start();

    //暂停几秒钟线程
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    new Thread(() -> {
      isStop = true;
    }, "t2").start();
  }
}

3.2. 通过AtomicBoolean

public class InterruptDemo {
  static volatile boolean isStop = false;
  static AtomicBoolean atomicBoolean = new AtomicBoolean(false);

  public static void main(String[] args) {
    m2();
  }

  public static void m2() {
    new Thread(() -> {
      while (true) {
        if (atomicBoolean.get()) {
          System.out.println("-----atomicBoolean.get() = true,程序结束。");
          break;
        }
        System.out.println("------hello atomicBoolean");
      }
    }, "t1").start();

    //暂停几秒钟线程
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    new Thread(() -> {
      atomicBoolean.set(true);
    }, "t2").start();
  }
}

3.3. 通过Thread类自带的中断api方法实现

public static void m3() {
  Thread t1 = new Thread(() -> {
    while (true) {
      if (Thread.currentThread().isInterrupted()) {
        System.out.println("-----isInterrupted() = true,程序结束。");
        break;
      }
      System.out.println("------hello Interrupt");
    }
  }, "t1");
  t1.start();

  try {
    TimeUnit.SECONDS.sleep(1);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }

  new Thread(() -> {
    t1.interrupt();//修改t1线程的中断标志位为true
  }, "t2").start();
}

4. 当前线程的中断标识为true,是不是就立刻停止

4.1. 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已

被设置中断标志的线程将继续正常运行,不受影响。所以, interrupt() 并不能真正的中断线程,需要被调用的 线程自己进行配合才行。

//中断为true后,并不是立刻stop程序
Thread t1 = new Thread(() -> {
    for (int i = 1; i <= 300; i++) {
        System.out.println("------i: " + i);
    }
    System.out.println("t1.interrupt()调用之后02: " + Thread.currentThread().isInterrupted());
}, "t1");
t1.start();

System.out.println("t1.interrupt()调用之前,t1线程的中断标识默认值: " + t1.isInterrupted());
try {
    TimeUnit.MILLISECONDS.sleep(3);
} catch (InterruptedException e) {
    e.printStackTrace();
}
//实例方法interrupt()仅仅是设置线程的中断状态位设置为true,不会停止线程
t1.interrupt();
//活动状态,t1线程还在执行中
System.out.println("t1.interrupt()调用之后01: " + t1.isInterrupted());

try {
    TimeUnit.MILLISECONDS.sleep(3000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
//非活动状态,t1线程不在执行中,已经结束执行了。
System.out.println("t1.interrupt()调用之后03: " + t1.isInterrupted());

4.2. 如果线程处于被阻塞状态(例如处于sleep, wait, join 等状态),在别的线程中调用当前线程对象的interrupt方法, 那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。

4.3. 中断异常需复位

sleep方法抛出InterruptedException后,中断标识也被清空置为false

我们在catch没有通过调用th.interrupt()方法再次将中断标识置为true,这就导致无限循环了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值