0
public class class_Q {
volatile boolean valueSet = false;
volatile int n;



synchronized int get()
{  
System.out.println("Now i am in get block and  valueset is : "+ valueSet  );
    if(!valueSet)
    {
        System.out.println("i am waiting in get block.....and releasing lock  ");
    try{
        wait();
    }catch(InterruptedException e)
        {
    System.out.println( "InterruptedException caught" );
        }
    }
    System.out.println( " value of n now in get block is  : " + n );
    valueSet=false;
    notify(); 
    return n; 
}


   synchronized void put(int n)
     {  
System.out.println(" Now i am in Put block and  valueset is : "+ valueSet);
if(valueSet) 
{
try
{
System.out.println("i am waiting in put block......and releasing lock. ");
wait();
}catch(InterruptedException e)
{
System.out.println( "InterruptedException caught" );
}
}
  this.n = n;
  valueSet = true;
  System.out.println( "the value of n now in put block is : " + n );
  notify();   
  }

}

 class Producer implements Runnable{
class_Q q;
Producer(class_Q q)
{
this.q = q;
new Thread( this, "Producer" ).start();
}
public void run()
{
    int i = 0;
    while(true)
    {
    q.put(i++);
    }
    }
} 


 class Consumer implements Runnable{
class_Q q;
 Consumer(class_Q q)
 {
    this.q = q;
    new Thread(this, "Consumer").start();
    }
  public void run()
  {
    while(true)
    {
        q.get();
        }
    }
  } 


  class PCFixed {
public static void main (String args[])
{
    class_Q q = new class_Q();
    new Producer(q);
    new Consumer(q);
    System.out.println( "Press Control-C to stop." );   
    }
} 

*出力**

今、私は get ブロックにいて、valueset は false です

私はgetブロックで待っています...そしてロックを解放しています

Control-C を押して停止します。

今、私はプットブロックにいて、値セットは: false

put ブロックの n の値は : 0

get ブロックの n の値は次のとおりです: 0

今、私は get ブロックにいて、valueset は false です

私はgetブロックで待っています...そしてロックを解放しています

今、私はプットブロックにいて、値セットは: false

put ブロックの n の値は : 1

get ブロックの n の値は : 1

出力の 6 行目以降、get() スレッドが (" notify() " ) put() スレッドを起動することを期待しています。誰かが get() スレッドを呼び出す背後にあるロジックを理解するのを手伝ってもらえますか (つまり、なぜそれが get ブロックにあるのですか?)

4

3 に答える 3

1

私はあなたのコードを再フォーマットし、ロギングメッセージを変更したので、すべてがはるかに明確になるはずです。

public class Test {
  static class class_Q {
    volatile boolean valueSet = false;
    volatile int n;

    synchronized int get() throws InterruptedException {
      System.out.println("get entering - valueSet=" + valueSet);
      // *** Changed from `if` to `while`
      while (!valueSet) {
        System.out.println("get waiting");
        wait();
      }
      // Clear to set the value.
      valueSet = false;
      // Tell any put waits to finish
      notify();
      System.out.println("get finished - n=" + n);
      return n;
    }

    synchronized void put(int n) throws InterruptedException {
      System.out.println("put entering - valueSet=" + valueSet);
      // *** Changed from `if` to `while`
      while (valueSet) {
        System.out.println("put waiting");
        wait();
      }
      this.n = n;
      valueSet = true;
      System.out.println("put finished - n=" + n);
      notify();
    }
  }

  static class Producer implements Runnable {
    class_Q q;

    Producer(class_Q q) {
      this.q = q;
    }

    public void run() {
      int i = 0;
      try {
        while (true) {
          q.put(i++);
          System.out.println("put(" + (i-1) + ")");
        }
      } catch (InterruptedException ex) {
        // Just exit the run loop and finish when interrupted.
      }
    }
  }

  static class Consumer implements Runnable {
    class_Q q;

    Consumer(class_Q q) {
      this.q = q;
    }

    public void run() {
      try {
        while (true) {
          int i;
          i = q.get();
          System.out.println("get(" + i + ")");
        }
      } catch (InterruptedException ex) {
        // Just exit the run loop and finish when interrupted.
      }
    }
  }

  public static void main(String args[]) {
    class_Q q = new class_Q();
    Thread producer = new Thread(new Producer(q));
    Thread consumer = new Thread(new Consumer(q));
    System.out.println("Press Control-C to stop.");
    producer.start();
    consumer.start();
  }
}

私も3つの主要な変更を加えました。interruptedスレッドを終了するだけのメカニズムを作成しました。ブロッキングテストを(while (x)の代わりにif (x))チェックするだけでなく、ブロックされた状態でループさせました。スレッドを自動起動しないようにしました。

このコードを今実行すると、プロセスがより明確になり、何が起こっているのかをよりよく理解できるようになるはずです。System.outこれはでありPrintWriter、したがってバッファリングできることを忘れないでください。

私が得る出力は次のとおりです。

入力してください--valueSet=false
終了しました-n=0
put(0)
入力してください--valueSet=true
待つ
Control-Cを押して停止します。
入力してください--valueSet=true
終了-n=0
完成した-n=1
put(1)
入力してください--valueSet=true
待つ
get(0)
入力してください--valueSet=true
終了-n=1
完成した-n=2
put(2)
入力してください--valueSet=true
待つ
get(1)
入力してください--valueSet=true
終了-n=2
get(2)
入力してください--valueSet=false
待つ
完成した-n=3
終了-n=3
get(3)
入力してください--valueSet=false
待つ
put(3)
入力してください--valueSet=false
完成した-n=4
終了する-n=4
get(4)
入力してください--valueSet=false
待つ
put(4)
..。
于 2012-06-01T22:35:16.650 に答える
0

これは、ブロッキング キューを使用した従来のプロデューサー/コンシューマー パターンです。キューがいっぱいの場合は、キューとブロックにデータを書き込みます (キューの現在の実装サイズ - 単一要素)。キューが空である間、コンシューマーはキューとブロック (待機) から読み取ります。

1 valueSet = false で get() を呼び出しています。wait() で停止します。

2 キュー オブジェクトを notify() する put() を呼び出し、get() メソッドで待機しているスレッドの実行をロック解除します。

于 2012-06-01T12:23:17.390 に答える
0

出力の 6 行目以降、get() スレッドが (" notify() " ) put() スレッドを起動することを期待しています。誰かが get() スレッドを呼び出す背後にあるロジックを理解するのを手伝ってもらえますか (つまり、なぜそれが get ブロックにあるのですか?)

Producer start, call put, valueSetis false, function from function return, and call put again, valueSettrue なので、待つ必要があります... で通知がなけれgetば、Consumer が書き込まれた値を読み取ったとしても、Producer は永久にブロックされます。 ..

in each は、notifyプロセスで先行していて、スレッドを待っていた他の参加者に、両方が同じスポットであることを知らせるために使用されます。

于 2012-06-01T12:13:47.397 に答える