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で述べたように、私はあなたが待機を呼び出し、queueオブジェクトに通知しなければならない...私は働くあなたのコードを得たことを

を考えます。 このようなオブジェクトは、staticをProducerとConsumerが共有すると宣言しなければならないと思います。

私は、コードが終了するまで実行を継続するためのwhileループを追加しました。ここでは生産と消費者第一wait

はそれであなたのコードである前にまた、余分なnotifyが必要とされている

が含まれる変更:

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

あなたはthis.wait()に相当しwait()を呼んでいるが、あなたはthisのモニターを持っていません。あなたはqueueにモニターを持っています。したがって、それはqueue.wait()でなければなりません。 (notify()と同じ)。

+0

私はいくつかのテストをしています...メンバー 'キュー'は、プロデューサとコンシューマが共有するために静的である必要はありませんか? – RubioRic

+0

これは受け入れられた答えだったはずです... –

3

チェックアウトは、IllegalMonitorStateException

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

あなたがモニターを持っていないそのオブジェクト上wait()(またはnotify())しようとすると例外がスローされるのJavadoc。キューで同期しましたが、wait()thisにしようとしました。これはキューではなく、実行可能です。 wait()からqueue.wait()およびnotify()からqueue.notify()に変更する必要があります。

0

スレッドは(通知呼び出すことができます)、またはすでにロックを取得したオブジェクトに対してのみwait()を実行します。あなたのプログラムでは、スレッドはキューオブジェクトをロックしており、スレッドはこれを待機しています。