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

} 

我在wait()部分得到一個java.lang.IllegalMonitorStateException。我想知道我在這裏做錯了什麼。有任何想法嗎??Java實現生產者消費者的拋出java.lang.IllegalMonitorStateException

我得到的完整例外情況如下。

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

提供完整的堆棧跟蹤請 – Jens

+1

在問題中添加。 – station

回答

2

我認爲我得到了你的代碼的工作...

正如JB Nizet說你必須調用wait和notify的queue對象。 我認爲這樣的對象必須聲明爲static才能被Producer和Consumer共享。

我已經包含循環代碼,以便繼續運行直到時間結束。

而且,額外的notify生產者和消費者第一之前,需要wait

這裏是你的代碼的改變包括:

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

消費者部分不工作。消費者線程最初開始並正在等待。製片人製作了所有元素,但消費者並沒有選擇。 – station

+0

您確定您已經複製了所有更改嗎?我剛剛運行它,它的工作 – RubioRic

+1

我的壞。我再次嘗試它的工作,謝謝 – station

6

你打電話wait(),這相當於this.wait(),但你不能拿着this顯示器。你正在拿着顯示器queue。所以它應該是queue.wait()。 (與notify()相同)。

+0

我正在做一些測試......成員'隊列'不必是靜態的才能被生產者和消費者共享? – RubioRic

+0

這應該是被接受的答案... –

0

一個線程可以調用notify()或僅在其已獲取鎖定的對象上等待()。在你的程序中,線程鎖定了隊列對象,然後你的線程正在等待這個。