面试突击:如何正确停止线程?

开发 前端
自定义中断标识也有一些问题,所以综合来看,interrupt 方法才是最理想的停止线程的方法,接下来我们一起来看它们的具体差异。

在 Java 中停止线程的实现方法有以下 3 种:

  • 自定义中断标识符,停止线程。
  • 使用线程中断方法 interrupt 停止线程。
  • 使用 stop 停止线程。

其中 stop 方法为 @Deprecated 修饰的过期方法,也就是不推荐使用的过期方法,因为 stop 方法会直接停止线程,这样就没有给线程足够的时间来处理停止前的保存工作,就会造成数据不完整的问题,因此不建议使用。而自定义中断标识也有一些问题,所以综合来看,interrupt 方法才是最理想的停止线程的方法,接下来我们一起来看它们的具体差异。

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;
}
}

以上代码的执行结果如下图所示:

我们期望的是:线程执行了步骤 1 之后,收到中断线程的指令,然后就不要再执行步骤 2 了,但从上述执行结果可以看出,使用自定义中断标识符是没办法实现我们预期的结果的,这就是自定义中断标识符,响应不够及时的问题。

2.interrupt中断线程

使用 interrupt 方法可以给执行任务的线程,发送一个中断线程的指令,它并不直接中断线程,而是发送一个中断线程的信号,把是否正在中断线程的主动权交给代码编写者。相比于自定义中断标识符而然,它能更及时的接收到中断指令,如下代码所示:

public static void main(String[] args) throws InterruptedException {
// 创建可中断的线程实例
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("thread 执行步骤1:线程即将进入休眠状态");
try {
// 休眠 1s
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("thread 线程接收到中断指令,执行中断操作");
// 中断当前线程的任务执行
break;
}
System.out.println("thread 执行步骤2:线程执行了任务");
}
});
thread.start(); // 启动线程

// 休眠 100ms,等待 thread 线程运行起来
Thread.sleep(100);
System.out.println("主线程:试图终止线程 thread");
// 修改中断标识符,中断线程
thread.interrupt();
}

以上代码的执行结果如下图所示:

从上述结果可以看出,线程在接收到中断指令之后,立即中断了线程,相比于上一种自定义中断标识符的方法来说,它能更及时的响应中断线程指令。

3.stop停止线程

stop 方法虽然可以停止线程,但它已经是不建议使用的废弃方法了,这一点可以通过 Thread 类中的源码发现,stop 源码如下:

从上面的图片可以看出,stop 方法是被 @Deprecated 修饰的不建议使用的过期方法,并且在注释的第一句话就说明了 stop 方法为非安全的方法。在最新版本 Java 中,此方法已经被直接移除了,所以强烈不建议使用。

总结

本文介绍了停止线程的 3 种方法:

  • 自定义中断标识符的停止方法,此方法的缺点是不能及时响应中断请求;
  • 使用 interrupt 中断线程方法,此方法是发送一个中断信号给线程,它可以及时响应中断,也是最推荐使用的方法;
  • 最后是 stop 方法,虽然它也可以停止线程,但此方法已经是过时的不建议使用的方法,在 Java 最新版本中已经被直接移除了,所以不建议使用。
责任编辑:武晓燕 来源: Java面试真题解析
相关推荐

2023-09-08 12:19:01

线程方法interrupt

2022-03-28 08:31:29

线程池定时任务

2022-04-06 07:50:28

线程安全代码

2022-04-18 07:36:37

TimeUnit线程休眠

2022-03-23 08:51:21

线程池Java面试题

2022-03-14 07:32:06

线程池拒绝策略自定义

2022-03-30 08:54:21

线程 Thread判断线程池任务Java

2022-01-24 07:01:20

安全多线程版本

2022-02-08 07:02:32

进程线程操作系统

2022-07-06 07:35:19

group byMySQL

2022-09-12 22:27:05

编程式事务声明式事务对象

2022-04-13 14:43:05

JVM同步锁Monitor 监视

2022-03-07 07:33:16

线程池Java语言

2022-03-16 07:33:40

守护线程用户线程语言

2022-03-02 07:36:37

池化技术Java线程池

2022-09-07 07:05:25

跨域问题安全架构

2022-04-07 07:40:40

线程安全变量

2022-03-21 07:40:08

线程池Executors方式

2022-07-11 07:10:48

HTTP协议类型

2022-04-11 07:40:45

synchroniz静态方法程序
点赞
收藏

51CTO技术栈公众号