Java/如何中断线程

Java/如何中断线程

先来说以下已经被抛弃的用于中断线程的方法: - 通过调用stop()方法停止线程 这种方法是不安全的。比如线程 A 调用线程 B 的stop()方法去停止 B 线程,但是 线程 A 是不知道线程 B 的执行情况的,这种突然的停止会导致线程 B 的一些清理工作还没完成就被强制停止了,而且线程 B 会立刻释放所占有的锁,这有可能会引发数据不同步的问题

  • 通过调用suspend()方法和resume()方法 这种方法也被抛弃了

目前推荐使用的方法是调用interrupt()方法,这种方法不是立刻中断线程,而是通知线程应该中断了,而被通知的线程何时中断,则由被通知的线程自己来处理。 - 如果线程处于被阻塞状态,那么线程将立刻推出被阻塞状态,并抛出一个 InterruptedException - 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,被设置中断标志的线程将继续正常运行,不受影响

因此,只使用interrupt()方法不能中断线程,需要被调用的线程配合中断 - 在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程 - 如果线程处于正常活动状态,那么会将该线程的中断表示设置为 true,被设置中断标志的线程将正常运行,不受影

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
public class InterruptedDemo {
public static void main(String[] args) throws InterruptedException {
Runnable task = new Runnable() {
@Override
public void run() {
int i = 0;
try {
//在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程
while (!Thread.currentThread().isInterrupted()) {
//子线程休眠 100 ms,这时如果主线程调用子线程的 interrupt() 方法,子线程会抛出异常。
Thread.sleep(100);
i++;
System.out.println(Thread.currentThread().getName()+"("+Thread.currentThread().getState()+") loop "+i);
}
} catch (InterruptedException e) {
//在调用阻塞方法时正确处理 InterruptedException 异常。(例如,catch 到异常后就终止线程)
System.out.println(Thread.currentThread().getName()+"("+Thread.currentThread().getState()+") catch InterruptedException");
}
}
};

Thread t1=new Thread(task,"t1");
System.out.println(t1.getName()+"("+t1.getState()+") is New");

t1.start();
System.out.println(t1.getName()+"("+t1.getState()+") is started");

//主线程休眠 300 ms,然后给 t1 发送中断指令
Thread.sleep(300);
t1.interrupt();
System.out.println(t1.getName()+"("+t1.getState()+") is interrupted");

//主线程休眠 300 ms,然后查看 t1 的状态
Thread.sleep(300);
System.out.println(t1.getName()+"("+t1.getState()+") is interrupted now");
}
}
上述代码的输出是:
1
2
3
4
5
6
7
t1(NEW) is New
t1(RUNNABLE) is started
t1(RUNNABLE) loop 1
t1(RUNNABLE) loop 2
t1(TIMED_WAITING) is interrupted
t1(RUNNABLE) catch InterruptedException
t1(TERMINATED) is interrupted now
线程休眠 100 ms,这时如果主线程调用子线程的 interrupt() 方法,子线程会抛出异常。子线程捕获到InterruptedException后,又会进入RUNNABLE状态。

评论