线程中断和线程终止


线程中断interrupt


  • interrupt()​ 的作用是中断当前线程

  • 当前线程可以中断本身运行的线程,如果其余线程调用本线程的​interrupt()​ 方法时,会通过​checkAccess()​ 检查权限,会抛出​SecurityException​异常
  • 如果本线程因为调用线程的​wait()​ 方法 ​,wait(long)​ 或者​wait(long, int),​ 或者是调用了线程的​join(), join(long),join(long, int),sleep(long),sleep(long, int)​ 进入阻塞状态时,调用​interrupt()​ 方法,那么该线程的 ​[中断状态]​ 就会被清除并且会收到一个​InterruptedException​异常
  • 如果线程阻塞在一个​Selector​选择器中,那么通过​interrupt()​ 中断时,线程的中断标记会被设置为​true,​ 并且会立即从选择操作中返回

  • 通过​interrupt()​ 中断线程时,中断标记会被设置为​true,​ 中断一个 ​[已经终止的线程]​ 不会产生任何操作

终止线程

阻塞状态

  • 一般情况下,通过中断​interrupt​方式终止处于 ​[阻塞状态]​ 的线程

  • 当前线程通过调用​sleep(),wait(),join()​ 等方法进入阻塞状态,若此时调用线程的​interrupt()​ 方法可以将线程的中断标记设置为​true
  • 由于处于阻塞状态,中断标记会被清除,同时产生一个​InterruptedException​异常
  • 将​InterruptedException​异常放在适当的位置就能终止线程

@Override
public void run() {
try {
while (true) {
// 运行线程
}
} catch (InterruptedException e) {
// 捕获到产生的InterruptedException异常,退出while(true)循环,线程终止
}
}

  • 在​while(true)​ 中不断执行任务,当线程处于阻塞状态时,调用线程的​interrupt()​ 产生​InterruptedException​异常,中断的异常在​while(true)​ 之外捕获,这样就可以退出​while​循环,终止异常
  • 对​InterruptedException​的捕获一般放在​while(true)​ 循环体外,这样就可以在产生异常时退出​while(true)​ 循环.如果对​InterruptedException​的捕获放置在​while(true)​ 循环体之内,就需要添加额外的退出处理

运行状态


  • 一般情况下,通过 ​[标记]​ 终止处于 ​[运行状态]​ 的线程
  • 标记包括: ​中断标记​和​额外添加标记

中断标记

@Override
public void run() {
while (!isInterrupted) {
// 运行线程
}
}

  • isInterrupted()​ 方法用于判断线程的中断标记是否为​true:
  • 当线程处于运行状态,并且需要终止时,可以调用线程的​interrupt()​ 方法,将线程的中断标记设置为​true.​ 此时​isInterrupted()​ 会返回​true,​ 此时就会退出​while​循环
  • interrupt()​ 并不会终止处于 ​[运行状态]​ 的线程,只是将线程的中断标记设置为​true

额外添加标记

private volatile boolean flag = true;

protected void stopTask() {
flag = false;
}

@Override
public void run() {
while (flag) {
// 运行任务
}
}

  • 线程中有一个​flag​标记,默认值为​true
  • 可以通过​stopTask()​ 方法来设置​flag​标记,当需要终止该方法时,调用该线程的​stopTask()​ 方法就可以让线程退出循环
  • 使用​volatile​定义​flag​类型: 保证​flag​的可见性.即其余线程通过调用​stopTask()​ 方法修改了​flag​的值之后,本线程可以看到修改后​flag​的值

综合状态线程


  • 综合状态线程:​ 处于阻塞状态和运行状态的线程
  • 综合状态线程的通用终止方式:

@Override
public void run() {
try {
// isInterrupted保证只要中断标记为true就终止线程
while (!isInterrupted()) {
// 运行线程
}
} catch (InterruptedException e) {
// InterruptedException保证只要当InterruptedException异常产生时就终止线程
}
}

interrupted()和isInterrupted()异同


  • 相同点:​ ​interrupted()​ 和​isInterrupted()​ 都能够用于检测对象的 ​[中断标记]
  • 不同点:

  • interrupted()​ 除了返回 ​[中断标记]​ 之外,还会清除 ​[中断标记],​ 即将 ​[中断标记]​ 设置为​false
  • isInterrupted()​ 仅仅返回 ​[中断标记]