You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何中断处于阻塞状态的线程?附Java代码示例分析

如何中断处于阻塞状态的线程?

首先直接给结论:不是所有阻塞状态都能被直接中断,这取决于线程阻塞的原因。我们先拆解你给出的例子,再一步步说明解决方案。

你的例子分析

在你的代码里,线程t2一开始是阻塞在synchronized (MUTEX)的锁等待队列中——Java的内置synchronized锁的等待是不可中断的。这时候调用t2.interrupt()只会给t2设置一个中断标记,但不会让它退出锁等待。只有当t1释放锁后,t2拿到锁进入Thread.sleep()时,sleep()方法会检查中断标记,抛出InterruptedException,这时候中断才生效。

不同阻塞类型的中断方式

Java里的线程阻塞主要分两类,对应不同的中断策略:

  • 可中断阻塞:这类阻塞会响应interrupt()调用,比如Thread.sleep()、Object.wait()、Thread.join(),以及java.util.concurrent包下的可中断锁等待(比如ReentrantLock.lockInterruptibly())。当线程处于这些阻塞状态时,调用interrupt()会让线程抛出InterruptedException,并清除中断标记。
  • 不可中断阻塞:比如等待synchronized内置锁、传统IO的阻塞(如Socket.accept()),这类阻塞不会响应interrupt(),调用interrupt()只会设置线程的中断标记,但线程会继续阻塞直到拿到锁/IO操作完成。

让锁等待可中断的解决方案

如果你想让线程在等待锁的时候就能被中断,不要用synchronized,改用java.util.concurrent.locks.ReentrantLock的lockInterruptibly()方法,它支持在等待锁时响应中断。

修改你的代码如下:

import java.util.concurrent.locks.ReentrantLock;

public class Main implements Runnable {
    static ReentrantLock LOCK = new ReentrantLock();

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread(new Main());
        Thread t2 = new Thread(new Main());
        System.out.println(t1.getId());
        System.out.println(t2.getId());
        t1.start();
        Thread.sleep(1000);
        t2.start();
        t2.interrupt();
        System.out.println("done main thread");
    }

    @Override
    public void run() {
        try {
            // 使用可中断的锁获取方式
            LOCK.lockInterruptibly();
            try {
                System.out.println(Thread.currentThread().getId());
                Thread.sleep(1000 * 10);
            } finally {
                LOCK.unlock();
            }
        } catch (InterruptedException ix) {
            System.out.println("Interrupt exception for:" + Thread.currentThread().getId());
            return;
        }
        System.out.println("done" + Thread.currentThread().getId());
    }
}

这个版本里,t2在调用lockInterruptibly()等待锁时,t2.interrupt()会直接触发InterruptedException,不需要等到进入sleep()再生效。

其他阻塞场景的中断

  • 对于传统IO阻塞(比如InputStream.read()),这类操作不会响应中断,你可以通过关闭流/套接字的方式让线程退出阻塞。
  • 对于NIO的通道(java.nio.channels.Channel),大多数支持中断,调用interrupt()会让阻塞的IO操作抛出ClosedByInterruptException。

内容的提问来源于stack exchange,提问作者Aladdin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:37:38