0

Я реализовал программу Продюсер-Потребитель, используя ReentrantLock и Condition. Моя реализация выполняется без каких-либо ошибок, если я сначала запустил нить производителя. Но если я сначала запускаю поток Consumer, я получаю исключение 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(); 
     } 
    } 

} 
+0

IllegalMonitorStateException - Брошенный в. указывают, что поток попытался подождать на мониторе объекта или уведомить другие потоки, ожидающие монитора объекта, не владея указанным монитором. – mcraen

+0

Я не знаю достаточно о потоке Java, чтобы быстро выбрать вашу ошибку, но это довольно описательное сообщение об ошибке – mcraen

+2

Можете ли вы попробовать использовать condition.await() вместо ожидания и посмотреть, разрешит ли это это? – Kamal

ответ

0

См аналогичный пример ниже, вы должны использовать ждать вместо ожидания и использовать условие возвращенное 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(); 
     } 
    } 
}