在 Java 中停止线程的实现方法有以下 3 种:
- 自定义中断标识符,停止线程。
- 使用线程中断方法 interrupt 停止线程。
- 使用 stop 停止线程。
1.自定义中断标识符 自定义中断标识符就是在程序中定义一个变量来决定线程是否要中断执行,具体实现代码如下:
class FlagThread extends Thread {
// 自定义中断标识符
public volatile boolean isInterrupt = false;
@Override
public void run() {
// 如果为 true -> 中断执行
while (!isInterrupt) {
// 业务逻辑处理
}
}
}
但自定义中断标识符的问题在于:线程中断的不够及时。因为线程在执行过程中,无法调用 while(!isInterrupt) 来判断线程是否为终止状态,它只能在下一轮运行时判断是否要终止当前线程,所以它中断线程不够及时,比如以下代码:
class InterruptFlag {
// 自定义的中断标识符
private static volatile boolean isInterrupt = false;
public static void main(String[] args) throws InterruptedException {
// 创建可中断的线程实例
Thread thread = new Thread(() -> {
while (!isInterrupt) { // 如果 isInterrupt=true 则停止线程
System.out.println("thread 执行步骤1:线程即将进入休眠状态");
try {
// 休眠 1s
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread 执行步骤2:线程执行了任务");
}
});
thread.start();
// 启动线程// 休眠 100ms,等待 thread 线程运行起来
Thread.sleep(100);
System.out.println("主线程:试图终止线程 thread");
// 修改中断标识符,中断线程
isInterrupt = true;
}
}
以上代码的执行结果如下图所示:
![面试突击 26(如何正确停止线程())](https://cdn.nlark.com/yuque/0/2022/png/92791/1643099720407-ff33542f-dd6c-4cf1-9202-f105d3f04735.png#clientId=uea0d03cc-e3a6-4&crop=0&crop=0&crop=1&crop=1&from=paste&<br />
文章图片 <br />
<br>我们期望的是:线程执行了步骤 1 之后,收到中断线程的指令,然后就不要再执行步骤 2 了,但从上述执行结果可以看出,使用自定义中断标识符是没办法实现我们预期的结果的,这就是自定义中断标识符,响应不够及时的问题。<br />
2.interrupt中断线程
使用 interrupt 方法可以给执行任务的线程,发送一个中断线程的指令,它并不直接中断线程,而是发送一个中断线程的信号,把是否正在中断线程的主动权交给代码编写者。相比于自定义中断标识符而然,它能更及时的接收到中断指令,如下代码所示:<br />
<blockquote><code>public static void main(String[] args) throws InterruptedException {
// 创建可中断的线程实例
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println()
以上代码的执行结果如下图所示:
![面试突击 26(如何正确停止线程())](https://cdn.nlark.com/yuque/0/2022/png/92791/1643100120280-8222c42b-91af-4156-b33c-fa0e05881633.png#clientId=uea0d03cc-e3a6-4&crop=0&crop=0&crop=1&crop=1&from=paste&<br />
文章图片 <br />
<br>从上述结果可以看出,线程在接收到中断指令之后,立即中断了线程,相比于上一种自定义中断标识符的方法来说,它能更及时的响应中断线程指令。<br />
3.stop停止线程
stop 方法虽然可以停止线程,但它已经是不建议使用的废弃方法了,这一点可以通过 Thread 类中的源码发现,stop 源码如下:<br><img alt=)
推荐阅读
- 面试突击20(进程和线程有什么区别())
- 面试突击17(HashMap除了死循环还有什么问题())
- 扒一扒@Retryable注解,很优雅,有点意思!
- 码农架构 | Spring Boot 实现通用 Auth 认证的 4 种方式
- 面试突击13(方法优先调用可选参数还是固定参数())
- 面试官(为什么不同返回类型不算方法重载())
- ClickHouse Keeper 源码解析
- 案例
- HashMap 有几种遍历方法(推荐使用哪种?)