当线程阻塞时,在线程上调用的中断不会抛出中断异常

Interrupt called on a thread doesn't throw Interrupted Exception when the thread is blocking

我正在尝试使用 ReentrantLock 和条件实现阻塞队列(仅在消费者端),但 运行 进入 JVM 不终止的状态。奇怪的是,一个线程被中断了,而另一个线程却没有。我确定我犯了一些错误,但就是不知道是什么。

编辑:

主要问题:当两个线程都阻塞在 condition.await

时,为什么只有一个线程抛出 interruptedexception

所以下面的代码只是我创建的一个示例。主要问题是开发一个生产者-消费者实现,我必须在其中创建一个模拟 class,它产生两种线程,客户和厨师,它们基于可重入锁同步。在执行了一些操作后(客户添加订单和厨师执行这些订单),我在客户线程上调用 join 以确保所有订单都已处理,然后停止 cook 线程,我在 cook 线程上调用中断以终止它们.但是只有一个线程抛出 interruptedexception 而第二个则没有。这是为什么?因为两个线程都在等待阻塞。

我的代码如下:

线程 class:

public class InterruptedThread implements Runnable{

    private final Lock lock;
    private final Condition condition;
    private final Queue<Integer> orderQueue;


    public InterruptedThread(Lock lock, Condition condition,Queue<Integer> orderQueue)
    {
        this.lock = lock;
        this.condition = condition;
        this.orderQueue = orderQueue;
    }

    @Override
    public void run() {

        try{
        while(true)
        {
            this.lock.lockInterruptibly();
            while(orderQueue.size() == 0 && !Thread.currentThread().isInterrupted())
            {
                   System.out.println("Inside blocking wait" + Thread.currentThread().getName());
                   condition.await();
            }

            int i = orderQueue.poll().intValue();
            System.out.println("Value read:" + i + "by thread" + Thread.currentThread().getName());
            this.lock.unlock();


        }
        }
        catch(InterruptedException ex)
        {
            System.out.println("Interrupted exception" + Thread.currentThread().getName());
            this.condition.signalAll();
            Thread.currentThread().interrupt();

        }

    }

}

主要class:

public class ExplicitLockCondition {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here

        Queue<Integer> orderQueue = new LinkedList<>();
        Lock lock = new ReentrantLock();
        Condition testCondition = lock.newCondition();

        Thread[] ths = new Thread[2];
        for(int i=0; i<ths.length;i++)
        {
            ths[i] = new Thread(new InterruptedThread(lock, testCondition,orderQueue));
            ths[i].start();
        }

        lock.lock();

        orderQueue.add(1);
        lock.unlock();

        lock.lock();
        orderQueue.add(2);
        lock.unlock();

        try {
            Thread.currentThread().sleep(5000);
        } catch (InterruptedException ex) {
            Logger.getLogger(ExplicitLockCondition.class.getName()).log(Level.SEVERE, null, ex);
        }

        lock.lock();
        orderQueue.add(-99);
        lock.unlock();


        for(int i=0; i<ths.length;i++)
        {
            ths[i].interrupt();

        }
        System.out.println("After loop exited!!!");
        for(int i=0; i<ths.length;i++)
        {
        System.out.println("Interrupted thread:" + ths[i].getName() +"with interrupt flag:" + ths[0].isInterrupted());
        }

        for(int i=0; i<ths.length;i++)
        {
            try {
                ths[i].join();
            } catch (InterruptedException ex) {
                Logger.getLogger(ExplicitLockCondition.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        System.out.println("Program exited!!!");

    }

}

你有

condition.await();

但你 signal 唯一的地方是 catch 街区。

在您的应用程序的典型 运行 中,您的 InterruptedThread(我们称之为 it1)将进入 while 循环,并且 await condition,让自己处于等待状态。您的 main 线程将做很多事情并最终中断 it1。您会注意到 Condition#await() 状态

的 javadoc

In all cases, before this method can return the current thread must re-acquire the lock associated with this condition.

所以线程it2重新获取锁,因为它被中断了

If the current thread:

  • has its interrupted status set on entry to this method; or
  • is interrupted while waiting and interruption of thread suspension is supported,

then InterruptedException is thrown and the current thread's interrupted status is cleared.

因此执行离开 while 块并转到 catch。在此期间,您的线程 it2 仍然拥有锁,因为没有 unlock 编辑它。 catch 块然后调用

this.condition.signalAll();

这表示 condition。线程 it1 然后正常完成。然而,Lock 仍然被锁定,没有任何东西可以获取它,这就是为什么你的另一个 InterruptedThread 无法从它的

中继续
condition.await();

基本上,您必须更好地管理 Lock 的锁定和解锁。

a) 在向队列中插入一个值后,您永远不会发出条件信号

b) 您的主题将离开

while(orderQueue.size() == 0 && !Thread.currentThread().isInterrupted())

如果被中断,则尝试从队列中轮询值。 如果那里没有值,将返回 null,你最终会遇到未捕获的空指针异常,但锁永远不会被解锁。

总是

lock.lock()l
try {
...
} finally {
lovk.unlovk();

}