原因是这样的,
new Thread(new Producer(buffer)).start();
new Thread(new Consumer(buffer)).start();
其实是开了两个线程,虽然你在buffer的底层方法加了锁,但是JVM执行线程的顺序是不可期待的,你可以通过设置线程的权值宏观地控制或者调用相关的方法,正如你执行的结果,其实只是其中一种结果,如果你多测试几次,结果应该是不同的,而且你每次put进去的数字是随即的,有这样的结果就很正常了。

解决方案 »

  1.   

    同意楼上的,
    不过,哪一个线程先SRART哪一个线程先抢点资源,然后直到更高级的线程抢点资源
    一般来说,你设置线程的优先级可以预计线程的执行,但也有些特别的,比如WINDOWS系统中,界面线程就较为优先
      

  2.   

    其实你的程序是对的:看看输出:
    public class ConProd {
    public static void main(String args[]) {
    Buffer buffer=new Buffer();
    new Thread(new Consumer(buffer)).start();
    new Thread(new Producer(buffer)).start();

    }
    }//临界资源
    class Buffer{
    int data;
    boolean dataready=false;
    Object lockProducer=new Object();

    public synchronized int get(){
        System.out.println("into gets");
    if (dataready==false){
    try{
    wait();
    }
    catch(InterruptedException e){
        e.printStackTrace();    
    }
    }
    dataready=false;
    System.out.println("get "+data);
    notifyAll();
    System.out.println("out get");
    return data;
    }

    public synchronized void put(int i){
        System.out.println("into put");
    if(dataready==true){
    try{
    wait();
    }catch(InterruptedException e){
        e.printStackTrace();
    }
    }
    data=i;
    dataready=true;
    System.out.println("put "+data);
    System.out.println("out put");
    notifyAll();
    }
    }//生产者
    class Producer implements Runnable{
    Buffer buffer;
    public Producer (Buffer buffer){
    this.buffer=buffer;
    }
    public void run(){
    int i;
    while(true){
        System.out.println("run Producer");
    try{
    Thread.sleep((int)Math.random()*1000);
    }catch(InterruptedException e){
        e.printStackTrace();    
    }
    i=(int)(Math.random()*100);
    buffer.put(i);
    //System.out.println(i+" produced.");
    }
    }
    }//消费者
    class Consumer implements Runnable{
    Buffer buffer;
    public Consumer (Buffer buffer){
    this.buffer=buffer;
    }
    public void run(){
    while(true){
        System.out.println("run Consumer");
    try{
    Thread.sleep((int)Math.random()*1000);
    }
    catch(InterruptedException e){
        e.printStackTrace();    
    }
    buffer.get();
    }
    }
    }
      

  3.   

    结果:
    run Consumer
    into gets
    run Producer
    into put
    put 35
    out put
    get 35
    out get
    run Consumer
    run Producer
    into gets
    into put
    put 30
    out put
    get 30
    out get
    run Consumer
    run Producer
    into gets
    into put
    put 77
    out put
    get 77
    out get
    run Consumer
    run Producer
    into gets
    into put
    put 96
    out put
    get 96
      

  4.   

    出现你的结果关键是因为:
    出现这种情况:
    当Consumer线程得到一个数退出get方法时(这是释放了线程锁),本来像立即输出得到地数据,哪知道,cpu被producer抢了,所以将执行set方法,所以有跟着输出了set地语句而没有输出get方法信息了
      

  5.   

    to usabcd(9号公路上的3名共军):
    昨天是在winXP上测试的。刚才在win2000下测试一切正常。看来和操作系统也有关系。to eddygtimegod(dark), azqf121(阿晚):
    如eddygtimegod所说,确实开了两个线程,但是product线程只开了一个。
    按照我的理解,put()方法既然已经加锁,那么在它执行完以前,dataready变量值任然是false;第二个试图进入的生产者对象应该被驻塞,那么它怎么会有机会再次调用System.out.println(i+" produced.")语句呢?
      

  6.   

    shangqiao(伤桥) 兄的看法颇有说服力,等我在XP上再试一下.
      

  7.   

    if(dataready==true){
    ^^while
    //:-)
      

  8.   

    接受 shangqiao(伤桥)的解释。