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

我正在等待获取块.....并释放锁定

按 Control-C 停止。

现在我在 Put 块中,valueset 是:false

现在 put 块中 n 的值是:0

现在 get 块中 n 的值是:0

现在我在 get 块中,valueset 是:false

我正在等待获取块.....并释放锁定

现在我在 Put 块中,valueset 是:false

现在 put 块中 n 的值是:1

现在 get 块中 n 的值是:1

在我的输出的第六行之后,我期待 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();
  }
}

我也做了三个主要的改变。我已经让interrupted机制退出了你的线程。我已经让您的阻塞测试在阻塞状态下循环,而不仅仅是检查它们(while (x)而不是if (x))。我已经让你的线程不会自动启动。

我认为如果你现在运行这段代码,流程应该更清晰,你应该能够更好地理解正在发生的事情。请记住,这System.out是 a PrintWriter,因此可以被缓冲。

我得到的输出是:

输入 - valueSet=false
完成 - n=0
放(0)
输入 - valueSet=true
等待
按 Control-C 停止。
进入 - valueSet=true
完成 - n=0
完成 - n=1
放(1)
输入 - valueSet=true
等待
得到(0)
进入 - valueSet=true
完成 - n=1
完成 - n=2
放(2)
输入 - valueSet=true
等待
得到(1)
进入 - valueSet=true
完成 - n=2
得到(2)
进入 - valueSet=false
等待
完成 - n=3
完成 - n=3
得到(3)
进入 - valueSet=false
等待
放(3)
输入 - valueSet=false
完成 - n=4
完成 - n=4
得到(4)
进入 - valueSet=false
等待
放(4)
...
于 2012-06-01T22:35:16.650 回答
0

在我的输出的第六行之后,我期待 get() 线程唤醒(“notify()”)put() 线程。有人可以帮助我理解调用 get() 线程背后的逻辑(换句话说,为什么它在 get 块中?)

Producer 启动,调用 put,valueSet为 false,从函数返回,再次调用 put,valueSet为 true,所以他必须等待......如果没有 notify in get,那么 Producer 将永远被阻塞,即使 Consumer 已读取写入的值。 ..

in each 用于向进程中领先的另一个参与者发出信号,该notify参与者正在等待后面的线程,他们现在都在同一个位置。

于 2012-06-01T12:13:47.397 回答
0

这是带有阻塞队列的经典生产者-消费者模式。如果队列已满,则将数据写入队列并阻塞(在队列的当前实现大小中 - 单个元素)。消费者从队列中读取数据并在队列为空时阻塞(等待)。

1 您使用 valueSet = false 调用 get()。它在 wait() 处停止。

2 您调用 put() 来通知()您的队列对象并解锁在 get() 方法中等待的线程的执行。

于 2012-06-01T12:23:17.390 回答