我正在尝试使用ReentrantLock和条件实现一个阻塞队列(仅在消费者端),但是我遇到了JVM没有终止的状态。奇怪的是,一个线程被中断但另一个线程没有被中断。我确信我犯了一些错误,但却无法弄清楚是什么。
编辑:
主要问题:为什么当两个线程在条件阻塞时,只有一个线程抛出interrupttedexception.await
所以下面的代码只是我创建的一个例子。主要的问题是开发一个生产者 - 消费者实现,我必须在其中创建一个模拟类,它产生两种线程,客户和厨师,它们是根据Reentrant锁同步的。在执行了一些操作(客户添加订单和厨师执行服务这些订单)之后,我调用了客户线程上的连接以确保所有订单都已处理然后停止烹饪线程,我在烹饪线程上调用中断来终止它们。但是只有一个线程抛出interrupttedexception而第二个没有抛出。这是为什么?因为两个线程都在等待阻塞。
我的代码如下:
线程类:
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();
}
}
}
主要课程:
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!!!");
}
}
答案 0 :(得分:1)
你有
condition.await();
,但signal
阻止catch
阻止它的唯一位置。
在您的应用程序的典型运行中,InterruptedThread
(让我们称之为it1
)将在while
循环和await
上condition
1}},使自己处于等待状态。你的main
线程会做很多事情并最终中断it1
。您将注意Condition#await()
个州的javadoc
在所有情况下,在此方法之前都可以返回当前线程 重新获得与此情况相关的锁定。
因此线程it2
重新获取锁定,因为它已被中断
如果是当前帖子:
- 在进入此方法时设置了中断状态;或
- 在等待时被中断,并且支持中断线程暂停,
然后
InterruptedException
被抛出和当前线程 中断状态被清除。
因此执行离开while
块并转到catch
。在此期间,您的帖子it2
仍然拥有锁,因为没有unlock
编辑它。然后catch
块调用
this.condition.signalAll();
表示condition
。线程it1
然后正常完成。但是,Lock
仍处于锁定状态,没有任何内容可以获取,这就是为什么您的其他InterruptedThread
无法继续使用
condition.await();
您基本上必须更好地管理锁定和解锁Lock
。
答案 1 :(得分:0)
a)在向队列中插入值
之后,您永远不会发出信号b)你的主题将离开
while(orderQueue.size() == 0 && !Thread.currentThread().isInterrupted())
如果它被中断,然后尝试从队列中轮询值。 如果那里没有值,那么将返回null并且你最终会得到未被捕获的空指针异常,但锁永远不会被解锁。
百达
lock.lock()l
try {
...
} finally {
lovk.unlovk();
}