/*
 *  生产者和消费者
 */
package com.liu.thread;public class TestDemo15 { public static void main(String[] args) {
Queue queue=new Queue();
Producer p=new Producer(queue);
Consumer c=new Consumer(queue);
new Thread(p).start();
new Thread(c).start();
}}class Producer implements Runnable{

private Queue queue;

public Producer(Queue queue)
{
this.queue=queue;
}

public void run(){
for(int i=0;i<10;i++)
{
System.out.println("Producer put:"+i);
queue.put(i);
}
}
}class Consumer implements Runnable{

private Queue queue;

public Consumer(Queue queue){
this.queue=queue;
}

public void run(){
while(true)
{
System.out.println("Consumer get:"+queue.get());
}
}
}class Queue{ private int value; private boolean isFull=false;

public synchronized void put(int value)
{
if(!isFull)
{
this.value=value;
isFull=true;
notify();
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello");
}

public synchronized int get()
{
if(!isFull)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isFull=false;
notify();
return value;
}
}
肖申克的救赎(372175908)  21:29:36
Producer put:0
Consumer get:0
hello
Producer put:1
Consumer get:1
hello
Producer put:2
hello
Producer put:3
Consumer get:2
Consumer get:3
hello
Producer put:4
Consumer get:4
hello
Producer put:5
Consumer get:5
hello
Producer put:6
Consumer get:6
hello
Producer put:7
Consumer get:7
hello
Producer put:8
Consumer get:8
hello
Producer put:9
Consumer get:9
hello谁能帮我解释下这个运行结果?为什么出现了连续put()的情况?wait()方法不是要等notify()调用后才会恢复吗?

解决方案 »

  1.   

    恩,notify()唤醒被wait()方法转化为等待状态的进程
      

  2.   

    consumer的notify唤醒等待中的producer,很正常啊。具体consumer和producer这两个线程谁执行打印语句快并不可控。
      

  3.   


    这个问题是Java规范里面明确说明的:第一,Java编译器是有所谓的优化编译执行的,语句并不一定绝对按照你书写的顺序来执行,所以,两个线程并不一定按照你的程序中书写的顺序严格交替执行。第二,Java虚拟机上多线程之间的执行顺序是一个线程调度问题,Java虚拟机有自己的调度算法,并不是按照简单的先来先执行的原则,而且,还可能在不同的时候运行同一个程序,其线程执行顺序也不一样。
      

  4.   

    Producer put:0
    hello
    Consumer get:0
    Producer put:1
    hello
    Consumer get:1
    Producer put:2
    hello
    Consumer get:2
    Producer put:3
    hello
    Consumer get:3
    Producer put:4
    hello
    Consumer get:4
    Producer put:5
    hello
    Consumer get:5
    Producer put:6
    hello
    Consumer get:6
    Producer put:7
    hello
    Consumer get:7
    Producer put:8
    hello
    Consumer get:8
    Producer put:9
    Consumer get:9
    hello
      

  5.   

    楼主用自己写的Queue用来模拟消费者与生产者的数据结构,但是我看了半天那个Queue,逻辑顺序看的我晕晕的,所以我就怀疑是不是楼主自己设计的queue逻辑思维不严谨所以才导致结果不对。我索性用ArrayBlockingQueue代替了楼主的Queue,这个类是Java提供的,功能也是模拟生产者消费者的关系,我把这个queue的容量设置成了1,就是说生产者线程往里面放东西,如果队列满了,就的等待,消费者线程往外取东西,如果里面是空的就的等待。这个java提供的ArrayBlockingQueue因该不会逻辑错误吧,人家应该实现的没有错误了吧。程序如下
    package CSDN;import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;public class BlockingQueueTest { public static void main(String[] args) {
    BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1);
    AProducer p = new AProducer(queue);
    AConsumer c = new AConsumer(queue); Thread pThread = new Thread(p, "Producer");
    Thread cThread = new Thread(c, "Producer"); pThread.start();
    cThread.start();
    }
    }class AProducer implements Runnable { private BlockingQueue<Integer> q; public AProducer(BlockingQueue<Integer> queue) {
    q = queue;
    } @Override
    public void run() {
    for (int i = 0; i <= 10; i++) {
    try {
    q.put(i);
    System.out.println("Producer put " + i);
    } catch (InterruptedException e) {
    e.printStackTrace();
    } }
    }
    }class AConsumer implements Runnable { private BlockingQueue<Integer> q; public AConsumer(BlockingQueue<Integer> queue) {
    q = queue;
    } @Override
    public void run() {
    while (true) {
    try {
    int i = q.take();
    System.out.println("Consumer get " + i);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }}
    运行后然后看看结果
    Producer put 0
    Producer put 1
    Consumer get 0
    Producer put 2
    Consumer get 1
    Producer put 3
    Consumer get 2
    Producer put 4
    Consumer get 3
    Producer put 5
    Consumer get 4
    Producer put 6
    Consumer get 5
    Producer put 7
    Consumer get 6
    Producer put 8
    Consumer get 7
    Producer put 9
    Consumer get 8
    Producer put 10
    Consumer get 9
    Consumer get 10结果还是不对,但是根据数字来看,应该程序跑起来是完全没有错误的,完全按照设想的走的。所以现在看来不能光按照println的显示来判断程序的运行顺序啊。
      

  6.   

    生产者-消费者要求: 
    1.多个生产者之间共用同一个锁。多个消费者之间共用同一个锁,生产者和消费者之间不能共用这个"排队"的锁。 
    2.不管生产者还是消费者来访问仓库都要上锁。Queue {
       private 仓库;
       private 生产排队;
       private 消费排队;   产品 get() {
          synchronize(消费排队){
             synchronize(仓库锁){
                 if(仓库空了){
                     仓库.wait(); //当仓库空了时,排队消费者队列中第一个消费者在等,它后面的消费者当然也在等,因为第一个人占用了消费者队列的锁。
                 }
                
                 产品 = 仓库.getFirst();
                 
                 仓库.notifyAll(); //告诉生产者仓库里有空位了。
                 
                 return 产品;
             }
          }
       }   void put(产品){
            synchronize(生产者排队){
                 synchronize(仓库锁){
                     if (仓库满了){
                        仓库.wait(); //仓库满了,第一个生产者在再,其它生产也在等,因为第一个人占用生产者排队的锁。
                     }                 仓库.putLast();                 仓库.notifyAll(); //告诉消费者仓库里有东西了。
                 }
            }   }}
      

  7.   

    是这个不?
    http://blog.csdn.net/KingWolfOfSky/archive/2010/04/08/5464990.aspx