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"); 
    } 

} 

Otrzymuję java.lang.IllegalMonitorStateException w wait() części. Chcę wiedzieć, co robię źle tutaj. Jakieś pomysły??wykonania Java Konsumenta Producer rzuca java.lang.IllegalMonitorStateException

Całkowity wyjątek, który otrzymuję, jest następujący.

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

Podaj pełną listę stosu proszę – Jens

+1

Dodano w pytaniu. – station

Odpowiedz

2

myślę, że mam swój kod działa ...

Jak stwierdził JB Nizet trzeba powołać czekać i powiadomić o obiekcie queue. Myślę, że taki obiekt musi zostać zadeklarowany jako static, aby mógł być udostępniany przez Producenta i Konsumenta.

Zawarłem pętle, aby kod działał do końca czasu.

także dodatkowy notify jest potrzebne przed Producentem a konsumentem wait

Oto kod z tym zmiany obejmowały:

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

Część konsumencka nie działa. Nić konsumenta rozpoczyna się początkowo i czeka. Producent wyprodukował wszystkie elementy, ale konsument nie odbiera. – station

+0

Czy jesteś pewien, że skopiowałeś wszystkie zmiany? Właśnie uruchomiłem go ponownie i działa – RubioRic

+1

My Bad. Próbowałem go ponownie, dziękuję – station

6

Dzwonisz wait(), co jest równoznaczne z this.wait(), ale nie jesteś trzymając monitor z this. Trzymasz monitor na queue. Więc powinno być queue.wait(). (to samo dla notify()).

+0

Przeprowadzam testy ... Kolejka użytkownika nie musi być statyczna, aby mogła być udostępniana przez producenta i konsumenta? – RubioRic

+0

To powinna być zaakceptowana odpowiedź ... –

3

Zapoznaj się z Javadoc dla IllegalMonitorStateException

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

jest wyjątek podczas próby wait() (lub notify()) na obiekcie, którego nie posiadają monitor; Zsynchronizowałeś się w kolejce, ale próbowałeś wait() na this, która nie jest kolejką, a raczej działającym. Zmiana wait() na queue.wait() i notify() na queue.notify() powinna działać.

0

Wątek może wywołać powiadomić() lub wait() tylko na obiekcie, na którym już posiada blokadę. W twoim programie wątek ma blokadę obiektu kolejki, a twój wątek dzwoni na to.

Powiązane problemy