MST

星途 面试题库

面试题:Java多线程编程中,如何正确使用线程中断机制来停止一个正在运行的线程?

请阐述在Java多线程环境下,通过`interrupt()`方法中断线程时,线程内部应该如何响应中断请求,以确保资源合理释放和线程安全停止。同时,说明`isInterrupted()`和`Thread.interrupted()`方法的区别及应用场景。
32.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

线程响应中断请求及资源释放

  1. 检查中断状态:在Java多线程环境下,当调用interrupt()方法中断线程时,线程内部应定期检查中断状态。通常在执行一些关键操作(如I/O操作、长时间计算等)的循环体中,使用Thread.currentThread().isInterrupted()来检查当前线程是否被中断。例如:
while (!Thread.currentThread().isInterrupted()) {
    // 线程执行的业务逻辑
    try {
        // 模拟耗时操作
        Thread.sleep(100);
    } catch (InterruptedException e) {
        // 处理中断异常,通常是重置中断状态
        Thread.currentThread().interrupt();
        break;
    }
}
  1. 释放资源
    • 文件资源:如果线程在执行过程中打开了文件,应在检测到中断请求后关闭文件。例如使用try - finally块:
FileInputStream fis = null;
try {
    fis = new FileInputStream("test.txt");
    while (!Thread.currentThread().isInterrupted()) {
        // 读取文件内容
        int data = fis.read();
        if (data == -1) break;
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fis != null) {
        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
- **网络资源**:如果线程涉及网络连接,如`Socket`,同样需要在中断时关闭连接。例如:
Socket socket = null;
try {
    socket = new Socket("localhost", 8080);
    while (!Thread.currentThread().isInterrupted()) {
        // 网络读写操作
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (socket != null) {
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  1. 确保线程安全停止:除了检查中断状态和释放资源,还需要确保对共享资源的访问是线程安全的。例如,使用synchronized关键字或Lock接口来保护共享资源。

isInterrupted()Thread.interrupted()方法的区别及应用场景

  1. 区别
    • isInterrupted():这是Thread类的实例方法,调用该方法不会改变线程的中断状态。例如:
Thread thread = new Thread(() -> {
    while (!Thread.currentThread().isInterrupted()) {
        // 线程执行逻辑
    }
});
thread.start();
thread.interrupt();
boolean isInterrupted = thread.isInterrupted(); // 这里获取的中断状态不会改变中断标识
- **`Thread.interrupted()`**:这是`Thread`类的静态方法,调用该方法不仅会返回当前线程的中断状态,而且会清除当前线程的中断状态(将中断标识位设为`false`)。例如:
Thread thread = new Thread(() -> {
    while (!Thread.interrupted()) {
        // 线程执行逻辑
    }
});
thread.start();
thread.interrupt();
boolean isInterrupted1 = Thread.interrupted(); // 获取中断状态并清除中断标识
boolean isInterrupted2 = Thread.interrupted(); // 再次调用返回false,因为标识已清除
  1. 应用场景
    • isInterrupted():适用于需要多次检查线程中断状态的场景,特别是在循环中持续判断中断状态而不希望清除中断标识的情况。例如,在一个需要不断轮询任务是否被中断的线程中:
while (!Thread.currentThread().isInterrupted()) {
    // 执行任务
}
- **`Thread.interrupted()`**:适用于在捕获`InterruptedException`异常后,需要处理中断逻辑并重置中断状态的场景。如前面在`Thread.sleep()`等会抛出`InterruptedException`异常的代码块中,捕获异常后调用`Thread.currentThread().interrupt()`来重置中断状态,也可以直接使用`Thread.interrupted()`来获取并清除中断状态。另外,在一些需要基于中断状态进行一次性处理的场景中也适用,因为它会清除中断状态,避免重复处理中断。