线程中断

什么是中断

  • 一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,所以, Thread.stop 、Thread.suspend 、Thread. resume 都已经被废弃了

  • 在 Java 中没有办法立即停止一条线程 , 然而停止线程却显得尤为重要 , 如取消一个耗时操作。因此 , Java提供了一种用于停止线程的机制 — 中断

  • 中断只是一种协作机制,Java 没有给中断增加任何语法,中断的过程完全需要程序员自己实现

  • 若要中断一个线程,你需要手动调用该线程的 interrupt 方法,该方法也仅仅是将线程对象的中断标识设为 true

  • 每个线程对象中都有一个标识,用于标识线程是否被中断 ; 该标识位为 true 表示中断,为 false 表示未中断;通过调用线程对象的interrupt 方法将线程的标识位设为 true ;可以在别的线程中调用,也可以在自己的线程中调用

中断的相关API

  1. void interrupt( )实例方法

    • interrupt( )仅仅是设置线程的中断状态为true,不会停止线程,(如果这个线程因为wait()、join()、sleep()方法在用的过程中被打断(interupt),会抛出Interrupted Exception)

    • 源码解读

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      public void interrupt() {
      if (this != Thread.currentThread())
      checkAccess();

      synchronized (blockerLock) {
      Interruptible b = blocker;
      if (b != null) {
      interrupt0(); // Just to set the interrupt flag
      b.interrupt(this);
      return;
      }
      }
      interrupt0();
      }

      Just to set the interrupt flag : 只是更改中断标志

  2. boolean isInterrupted( )实例方法

    返回当前 线程的终端标志

  3. static boolean interrupted( )静态方法

    判断线程是否被中断,并清楚当前中断状态

    假设有两个线程A、B ,线程B调用了 interrupt 方法,这个时候我们连接调用两次 isInterrupted 方法,第一次会返回 true , 然后这个方法会将中断标识位设置位 false ,所以第二次调用将返回 false

    1
    2
    3
    4
    5
    6
    7
    System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());//   main---false
    System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());// main---false
    System.out.println("111111");// 111111
    Thread.currentThread().interrupt();///----false---> true
    System.out.println("222222");// 222222
    System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());//main---true
    System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());//main---false

使用中断标识停止线程

  • volatile 变量实现
  • AtomicBoolean 变量实现
  • interrupt 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package tech.chen.juccode.a10;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* @Date 2022/8/22 11:47
* @Author c-z-k
*/
public class InterruptedDemo {
private static volatile boolean IS_STOPPED = false;
private static AtomicBoolean flag = new AtomicBoolean(false);
public static void main(String[] args) {

// m3();
// m2();
m1();
}
private static void m1() {
Thread thread = new Thread(() -> {
while (true){
if(flag.get()){
System.out.println(Thread.currentThread().getName() + "\t 使用 AtomicBoolean 已被中断");
break;
}
System.out.println(Thread.currentThread().getName() + "\t 使用 AtomicBoolean 正在执行");
}
},"t1");
thread.start();

new Thread(()->{
flag.set(true);
},"t2").start();
}
private static void m2() {
Thread thread = new Thread(() -> {
while (true){
if(IS_STOPPED){
System.out.println(Thread.currentThread().getName() + "\t 使用 volatile 已被中断");
break;
}
System.out.println(Thread.currentThread().getName() + "\t 使用 volatile 正在执行");
}
},"t1");
thread.start();

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

private static void m3() {
Thread thread = new Thread(() -> {
while (true){
if(Thread.currentThread().isInterrupted()){
System.out.println(Thread.currentThread().getName() + "\t 已被中断");
break;
}
System.out.println(Thread.currentThread().getName() + "\t 正在执行");
}
},"t1");
thread.start();

new Thread(()->{
thread.interrupt();
},"t2").start();
}
}