Проблема с источником-потребителем, использующим блокировку и условие
Я реализовал программу Producer-Consumer, используя ReentrantLock и Condition. Моя реализация запускается без каких-либо ошибок, если я сначала запускаю поток 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();
}
}
}
1 ответ
Смотрите аналогичный пример ниже, вы должны использовать await вместо wait и использовать Condition, возвращаемое ReentrantLock, что вы уже делаете (см. Документ Java для ReeentrantLock):
package reentrant_prodcons;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Reentrant_ProdCons {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Queue<Integer> queue=new LinkedList<Integer>();
ReentrantLock lock=new ReentrantLock();
Condition con=lock.newCondition();
final int size = 5;
new Producer(lock, con, queue, size).start();
new Consumer(lock, con, queue).start();
}
}
class Producer extends Thread{
ReentrantLock lock;
Condition con;
Queue<Integer> queue;
int size;
public Producer(ReentrantLock lock, Condition con, Queue<Integer> queue, int size) {
this.lock = lock;
this.con = con;
this.queue = queue;
this.size=size;
}
public void run(){
for(int i=0;i<10;i++){
lock.lock();
while(queue.size()==size){
try {
con.await();
} catch (InterruptedException ex) {
Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
}
}
queue.add(i);
System.out.println("Produced : "+i);
con.signal();
lock.unlock();
}
}
}
class Consumer extends Thread{
ReentrantLock lock;
Condition con;
Queue<Integer> queue;
public Consumer(ReentrantLock lock, Condition con, Queue<Integer> queue) {
this.lock = lock;
this.con = con;
this.queue = queue;
}
public void run(){
for(int i=0;i<10;i++){
lock.lock();
while(queue.size()<1){
try {
con.await();
} catch (InterruptedException ex) {
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
}
}
System.out.println("Consumed : "+queue.remove());
con.signal();
lock.unlock();
}
}
}