【发布时间】:2016-09-13 17:42:24
【问题描述】:
我已经使用 ReentrantLock 和 Condition 实现了 Producer-Consumer 程序。如果我先启动 Producer 线程,我的实现运行不会出现任何错误。但是如果我首先启动消费者线程,我会得到一个 IllegalMonitorStateException。请指出我的程序有什么问题。
这是我的实现。
public class ProducerConsumerReentrantLock {
public static void main(String[] args) throws InterruptedException {
List<Integer> list = new ArrayList<Integer>(10);
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
int limit=10;
ProductionTaskReentrantLock produce = new ProductionTaskReentrantLock(lock, condition, limit, list);
ConsumptionTaskReentrantLock consume = new ConsumptionTaskReentrantLock(lock, condition, limit, list);
Thread productionWorker = new Thread(produce,"Producer");
Thread consumptionWorker = new Thread(consume,"Consumer");
consumptionWorker.start();
productionWorker.start();
// consumptionWorker.start();
productionWorker.join();
consumptionWorker.join();
}
}
.
class ProductionTaskReentrantLock implements Runnable{
List<Integer> list = null;
ReentrantLock lock;
Condition condition;
int limit;
public ProductionTaskReentrantLock(ReentrantLock lock, Condition condition, int limit, List<Integer> list) {
super();
this.lock = lock;
this.condition = condition;
this.limit = limit;
this.list = list;
}
@Override
public void run() {
lock.lock();
try{
for (int i = 0; i < 10 ; i++) {
while(list.size()==limit){
try {
System.out.println("List is full");
condition.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced "+i);
list.add(i);
System.out.println(list);
condition.signalAll();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
}
}
}
.
class ConsumptionTaskReentrantLock implements Runnable{
List<Integer> list = null;
ReentrantLock lock;
Condition condition;
int limit;
public ConsumptionTaskReentrantLock(ReentrantLock lock, Condition condition, int limit, List<Integer> list) {
super();
this.lock = lock;
this.condition = condition;
this.limit = limit;
this.list = list;
}
@Override
public void run() {
lock.lock();
try{
for (int i = 0; i < 10 ; i++) {
while(list.isEmpty()){
try {
System.out.println("List is empty");
condition.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consumed "+list.remove(0));
System.out.println(list);
condition.signalAll();
}
} finally {
lock.unlock();
}
}
}
【问题讨论】:
-
IllegalMonitorStateException - 抛出该异常以指示线程已尝试在对象的监视器上等待或通知其他线程在对象的监视器上等待但不拥有指定的监视器。
-
我对 Java 线程的了解不够,无法快速找出您的错误,但这是一个非常具有描述性的错误消息
-
你可以尝试使用 condition.await() 而不是等待,看看是否能解决这个问题?
-
@Kamal:这就是答案。 每个对象都有一个
wait()方法——甚至是Condition对象——你不能调用它,除非在那个对象上synchronized。
标签: java multithreading concurrency synchronization reentrantlock