对于一个需要被终止的线程,大体上有三种方法来退出它。
大家肯定有听说过 stop()
方法,通过 stop()
方法可以很方便地终止一个线程,但是它在结束一个线程地时候不会保证线程地资源正常释放。假如有一个线程正在处理一个复杂地业务流程,这个线程突然间被调用 stop()
方法而意外终止,此时地业务数据可能会产生不一致地问题。正是因为这个原因,stop()
方法被标记为 @Deprecated 被废弃地方法,JDK 在以后的版本中可能会移除它,不推荐使用。
标志位
利用 volatile 关键字实现多线程之间共享变量的可见性这一特点来实现。
1 | private volatile static boolean stop = false; |
interrupt
当其他线程通过调用当前线程的 interrupt 方法,表示向当前线程打个招呼,告诉他可以中断线程的执行了。这里又分为两种情况:
线程处于阻塞状态:当前线程被 sleep、Thread.wait、Thread.join 三种方法之一阻塞时,调用当前线程的 interrupt 方法会抛出 InterruptedException 异常。通过捕获该异常,然后进行结束线程操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public static void main(String[] args) throws Exception {
Thread thread = new Thread(() -> {
while (true) {
try {
// 阻塞
Thread.sleep(10000);
} catch (InterruptedException e) {
// 抛出该异常,会将复位标识设置为false
System.out.println(Thread.currentThread().isInterrupted());
e.printStackTrace();
// 退出循环
break;
}
}
});
thread.start();
// 设置中断标识,中断标识为true
thread.interrupt();
TimeUnit.SECONDS.sleep(1);
System.out.println(thread.isInterrupted()); // false
}线程未处于阻塞状态:使用
isInterrupt()
方法判断线程的中断标志来退出循环。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public static void main(String[] args) throws Exception {
Thread thread = new Thread(() -> {
while (true) {
boolean interrupted = Thread.currentThread().isInterrupted();
if (interrupted) {
System.out.println("before: "+ interrupted); // true
// 【清除打断标记】对线程进行复位,中断标识为false
Thread.interrupted();
System.out.println("after: "+ Thread.currentThread().isInterrupted()); // false
// 跳出循环
break;
}
}
});
thread.start();
// 设置中断标识,中断标识为true
thread.interrupt();
}
两阶段终止模式
1 | class TwoPhaseTermination { |