线程中断机制(interrupt)

参考博文:Thread中interrupted()方法和isInterrupted()方法区别总结
廖雪峰的参考博文,最靠谱的做法

首先讲 interrupt() 方法:

interrupt()方法只是改变中断状态,不会中断一个正在运行的线程。需要用户自己去监视线程的状态为并做处理。

  1. interrupt 中断操作时,非自身打断需要先检测是否有中断权限,这由jvm的安全机制配置;

  2. 如果线程处于sleep, wait, join 等状态,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常;

  3. 如果线程处于I/O阻塞状态,将会抛ClosedByInterruptException(IOException的子类)异常;

  4. 如果线程在Selector上被阻塞,select方法将立即返回;

  5. 如果非以上情况,将直接标记 interrupt 状态;

    注意:interrupt 操作不会打断所有阻塞,只有上述阻塞情况才在jvm的打断范围内,如处于锁阻塞的线程,不会受 interrupt中断;

interrupted()和isInterrupted()方法说明

isInterrupted(),用来判断当前线程的中断状态(true or false)。
interrupted()是个Thread的static方法,内部调用了isInterrupted()方法,所以他首先会判断线程是否处于中断状态,其次他还可以用来恢复中断状态。
下面是源码说明:

  public boolean isInterrupted() {
        return isInterrupted(ClearInterrupted:false); //表示并不会重置中断标志位。
    }
public static boolean interrupted() {
        return currentThread().isInterrupted(ClearInterrupted:true);  //表示会重置中断标志位
    }

上面两个方法调用的方法如下:
作用是:测试某个线程是否被中断。中断状态将根据传递的clear的值重置或不重置----所以有两个功能;
1.首先返回的是线程是否被中断,
2.中断状态是否被重置取决于传入的值。

 /**
     * Tests if some Thread has been interrupted.  The interrupted state
     * is reset or not based on the value of ClearInterrupted that is
     * passed.
     */
    private native boolean isInterrupted(boolean ClearInterrupted);

测试

阻塞情况下中断,抛出异常后线程恢复非中断状态,即 interrupted = false

public class ThreadTest {
    
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Task("1"));
        t.start();
        t.interrupt();
    }

    static class Task implements Runnable{
        String name;
        
        public Task(String name) {
            this.name = name;
        }
        
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("thread has been interrupt!");
            }
            System.out.println("isInterrupted: " + Thread.currentThread().isInterrupted());
            System.out.println("task " + name + " is over");
        }
    }
}

输出:

thread has been interrupt!
isInterrupted: false
task 1 is over

调用Thread.interrupted() 方法后线程恢复非中断状态

public class ThreadTest {
    
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Task("1"));
        t.start();
        t.interrupt();
    }

    static class Task implements Runnable{
        String name;
        
        public Task(String name) {
            this.name = name;
        }
        
        @Override
        public void run() {
            System.out.println("first :" + Thread.interrupted());
            System.out.println("second:" + Thread.interrupted());
            System.out.println("task " + name + " is over");
        }
    }
}

输出结果

first :true
second:false
task 1 is over

总结

所以想要中断一个线程:需要堵塞状态(sleep(),wait(),join())+线程中断标志(interrupt())两者配合使用,那么该线程将抛出一个 InterruptedException中断异常(该线程必须事先预备好处理此异常),从而提早地终结被阻塞状态。如果线程没有被阻塞,这时调用 interrupt()将不起作用,直到执行到wait(),sleep(),join()时,才马上会抛出 InterruptedException。
无论是先中断还是先阻塞最后都能达到停止线程的目的----------异常中断法。

### Java 线程 `interrupt` 方法的使用 在 Java 中,线程的 `interrupt()` 方法用于请求中断某个线程的操作。它并不会立即停止线程的运行,而是通过设置线程的中断状态来通知该线程应该停止其当前活动[^1]。 #### 基本概念 当调用 `thread.interrupt()` 时,如果目标线程处于阻塞状态(如等待 I/O 或者调用了 `sleep()`),那么会抛出 `InterruptedException` 并清除其中断标志位;如果线程未被阻塞,则仅设置其中断状态,可通过 `isInterrupted()` 来检测这一状态[^2]。 以下是几个典型的使用场景: --- #### 场景一:线程正在执行阻塞操作 当线程正在进行某些阻塞操作(例如 `Thread.sleep()` 或 `Object.wait()`)时,调用 `interrupt()` 将引发 `InterruptedException`,并自动重置线程的中断状态为 false。 ```java public class InterruptExample { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { try { System.out.println("Thread is sleeping..."); Thread.sleep(5000); System.out.println("Thread woke up after sleep."); } catch (InterruptedException e) { System.out.println("Thread was interrupted during sleep."); } }); t1.start(); Thread.sleep(1000); // 让主线程稍作延迟以便观察效果 t1.interrupt(); System.out.println("Main thread finished."); } } ``` 在这个例子中,子线程尝试休眠 5 秒钟,但在休眠期间被主线程中断,因此捕获到了 `InterruptedException`[^3]。 --- #### 场景二:线程未处于阻塞状态 如果线程并未执行任何阻塞操作,调用 `interrupt()` 只会简单地设置线程的中断状态为 true。此时不会有任何异常发生,序可以定期检查此状态以决定如何响应中断信号。 ```java public class NonBlockingInterruptExample { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { System.out.println("Running..."); try { Thread.sleep(1000); // 模拟工作负载 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 break; } } System.out.println("Thread received interruption signal and will exit gracefully."); }); t1.start(); Thread.sleep(3000); // 给子线程一些时间运行 t1.interrupt(); System.out.println("Main thread has sent an interrupt request to the child thread."); } } ``` 在此示例中,即使线程没有进入真正的阻塞态,也可以通过轮询 `isInterrupted()` 的返回值实现优雅退出逻辑[^4]。 --- #### 关键点总结 - **中断状态**:每次成功调用 `interrupt()` 后都会改变对应线程的状态标记。 - **异常处理机制**:对于那些可能触发 `InterruptedException` 的 API 调用来说,务必妥善编写错误处理器。 - **恢复中断状态的最佳实践**:一旦捕获到 `InterruptedException` ,通常建议重新设定中断标志 (`Thread.currentThread().interrupt()`),从而允许更高层代码继续感知原始中断事件的发生。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值