6
import java.util.LinkedList; 
import java.util.Queue; 

class Producer extends PubSub implements Runnable{ 

    @Override 
    public void run() { 
     synchronized(queue){ 
      if (queue.size() == 99){ 
       try { 
        wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      queue.add(2); 
      try{ 
       Thread.sleep(1000); 
      } 
      catch (InterruptedException e){ 
       e.printStackTrace(); 
      } 
      notify(); 
      } 
     }  
} 


class Consumer extends PubSub implements Runnable{ 

    @Override 
    public void run() { 
     synchronized(queue){ 
      if(queue.isEmpty()){ 
       try { 
        wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      System.out.println(queue.poll()); 
     } 

    } 

} 
public class PubSub { 
    static Integer QUEUE_SIZE = 100; 
    Queue<Integer> queue = new LinkedList<Integer>(); 
    public static void main(String[] args) { 
     Producer producer = new Producer(); 
     Consumer consumer = new Consumer(); 
     Thread producerThread = new Thread(producer); 
     Thread consumerThread = new Thread(consumer); 
     producerThread.start(); 
     consumerThread.start(); 
     System.out.println("Started both the threads"); 
    } 

} 

sto ottenendo un java.lang.IllegalMonitorStateException nella parte wait(). Voglio sapere cosa sto facendo male qui. Qualche idea??implementazione Java di produttore consumatore getta java.lang.IllegalMonitorStateException

L'eccezione completa che ottengo è la seguente.

Exception in thread "Thread-1" Started both the threads 
java.lang.IllegalMonitorStateException 
    at java.lang.Object.wait(Native Method) 
    at java.lang.Object.wait(Object.java:502) 
    at Consumer.run(PubSub.java:36) 
    at java.lang.Thread.run(Thread.java:745) 
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notify(Native Method) 
    at Producer.run(PubSub.java:23) 
    at java.lang.Thread.run(Thread.java:745) 
+2

Fornire lo stacktrace completo per favore – Jens

+1

Aggiunto nella domanda. – station

risposta

2

penso che ho ottenuto il vostro codice di lavoro ...

Come affermato da JB Nizet bisogna richiamare attesa e informare sull'oggetto queue. Penso che tale oggetto debba essere dichiarato static da condividere da produttore e consumatore.

Ho incluso cicli mentre il codice continuava a funzionare fino alla fine del tempo.

Inoltre, un extra notify è necessario prima di produttore e consumatore prima wait

Ecco il codice con che cambia incluso:

import java.util.LinkedList; 
import java.util.Queue; 

class Producer extends PubSub implements Runnable{ 

    @Override 
    public void run() { 
     int index = 0; 

     while (true) { 
      synchronized(queue){ 
       while (queue.size() == QUEUE_SIZE){ 
        try { 
         System.out.println("Producer waits"); 
         queue.notify(); 
         queue.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 

       System.out.println("Produce element " + (++index)); 
       queue.add(2); 
       queue.notify(); 

       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e){ 
        e.printStackTrace(); 
       } 


      } 
     } 
    } 
} 


class Consumer extends PubSub implements Runnable{ 

    @Override 
    public void run() { 
     while (true) { 
      synchronized(queue) { 

       while (queue.isEmpty()){ 
        try { 
         System.out.println("Consumer waits"); 
         queue.notify(); 
         queue.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 

       System.out.println("Consume element " + queue.poll()); 
       queue.notify(); 

      } 
     } 

    } 

    } 

public class PubSub { 
    static Integer QUEUE_SIZE = 100; 

    static Queue<Integer> queue = new LinkedList<Integer>(); 

    public static void main(String[] args) { 
      Producer producer = new Producer(); 
      Consumer consumer = new Consumer(); 

      Thread producerThread = new Thread(producer); 
      Thread consumerThread = new Thread(consumer); 

      producerThread.start(); 
      consumerThread.start(); 

      System.out.println("Started both the threads"); 
    } 

} 

enter image description here

+0

La parte del consumatore non funziona. Il thread del consumatore inizia inizialmente e sta aspettando. Il produttore ha prodotto tutti gli elementi ma poi il consumatore non ha raccolto. – station

+0

Sei sicuro di aver copiato tutte le modifiche? Ho appena eseguito di nuovo e funziona – RubioRic

+1

My Bad. L'ho provato di nuovo funziona, grazie – station

6

si sta chiamando wait(), che equivale a this.wait(), ma non tiene in mano il monitor di this. Stai tenendo il monitor su queue. Quindi dovrebbe essere queue.wait(). (stesso per notify()).

+0

Sto facendo dei test ... La "coda" dei membri non deve essere statica per essere condivisa da Producer e Consumer? – RubioRic

+0

Questa dovrebbe essere la risposta accettata ... –

3

Scopri i Javadoc per IllegalMonitorStateException

https://docs.oracle.com/javase/7/docs/api/java/lang/IllegalMonitorStateException.html

L'eccezione viene generata quando si tenta di wait() (o notify()) su un oggetto di cui non si tiene il monitor; Si è sincronizzato sulla coda, ma si è tentato di wait() su this, che non è la coda, ma è eseguibile. Cambiare wait() a queue.wait() e notify() a queue.notify() dovrebbe funzionare.

0

Un thread può chiamare notify() o wait() solo su un oggetto su cui ha già acquisito il blocco. Nel thread del programma è bloccato l'oggetto in coda e quindi il thread sta chiamando in attesa su questo.