解决方案 »

  1.   

    public class ProduceConsume
    {
    public static void main(String[] args)
    {
    syncstack ss = new syncstack();
    produce p = new produce(ss);
    consume c = new consume(ss);

    Thread t1 = new Thread(p);
    Thread t2 = new Thread(c);

    t1.start();
    t2.start();
        }
    }class syncstack
    {
    int cnt = 0;
    char[] data = new char[6];
    char ch;

    public synchronized void push(char ch)
    {
    while (cnt == data.length)
    {
    try
    {
    this.wait();
    }
    catch(Exception e)
    {
    }
    //this.notify();
        }
        this.notify();
        
        data[cnt] = ch;
        cnt++;
        System.out.printf("生产了%c\n", ch);
        System.out.printf("当前容器共有%d个物品\n", cnt);
        
    }  public synchronized void pop()
    {
    char ch;
    while(cnt ==0)
    {
    try
    {
    this.wait();
    }
    catch(Exception e)
    {
    }
                //this.notify();
            }
    this.notify();
    ch = data[cnt-1];
    --cnt;
    System.out.printf("消费了物品%c\n", ch);
    System.out.printf("当前还剩下%d个物品\n", cnt);

    //return ch;
     }
    }
    class produce implements Runnable
    {
    syncstack ss = null;
    public produce(syncstack ss)
    {
    this.ss = ss;
    }

    public void run()
    {
    char ch;
    for(int i=0; i<20; i++)
    {
     ch = (char)('a'+i);
     ss.push(ch);
    }
    }

    }class consume implements Runnable
    {
    syncstack ss = null;
    public consume(syncstack ss)
    {
    this.ss =ss;
    }
    public void run()
    {
    for(int i=0; i<20; i++)
    {
    ss.pop();
    try
    {
    Thread.sleep(500);
    }
    catch(Exception e)
    {}
    }
    }
    }
      

  2.   

    OS作业?监视器模型让你的代码结构很乱。
    为什么不用系统java.util.concurrent.Semaphore?结构更清楚
      

  3.   

    public synchronized void push(char ch) 
        {
            while (cnt == data.length)
            {
             System.out.println("1111111");
                try
                {
                 System.out.println("3333333");
                 this.wait();
                   
                }
                catch(Exception e)
                {
                 e.printStackTrace();
                }
               
                this.notify();
                System.out.println("call thread consume");
            }
            //this.notify();
             
            data[cnt] = ch;
            cnt++;
            System.out.printf("生产了%c\n", ch);
            System.out.printf("当前容器共有%d个物品\n", cnt);
             
        }   
    this.wait()调用后,后面的this.notify()还能执行吗?线程都已经停止了,当然this.notify()是不能够执行到的,结果就是你没办法唤醒线程了, 解决的办法是将this.notify()放到this.wait()之前去,这样就ok了改后代码package thread.mypackage;public class ProduceConsume
    {
        public static void main(String[] args)
        {
            syncstack ss = new syncstack();
            produce p = new produce(ss);
            consume c = new consume(ss);
             
            Thread t1 = new Thread(p);
            Thread t2 = new Thread(c);
             
            t1.start();
            t2.start();
        }   
    }
     
    class syncstack
    {
        static int cnt = 0;
        char[] data = new char[6];
        char ch;
         
        public synchronized void push(char ch) 
        {
            while (cnt == data.length)
            {
             //System.out.println("1111111");
                try
                {
                 this.notify(); 
                 //System.out.println("3333333");
                 this.wait();
                   
                }
                catch(Exception e)
                {
                 e.printStackTrace();
                }
               
                //this.notify();
                System.out.println("call thread consume");
            }
            //this.notify();
             
            data[cnt] = ch;
            cnt++;
            System.out.printf("生产了%c\n", ch);
            System.out.printf("当前容器共有%d个物品\n", cnt);
             
        } 
     
        public synchronized void pop() 
        {
            char ch;
            while(cnt ==0)
            {
               try
                {
                 this.notify(); 
                    this.wait();
                   // System.out.println("22222222222222222222");
                }
                catch(Exception e)
                {
                 e.printStackTrace();
                }
                
               // this.notify();       
                System.out.println("call produce thread");
            }
            //this.notify();
            ch = data[cnt-1];
           
            --cnt;
            System.out.printf("消费了物品%c\n", ch);
            System.out.printf("当前还剩下%d个物品\n", cnt);
             
            //return ch;
             }
    }
    class produce implements Runnable
    {
        syncstack ss = null;
        public produce(syncstack ss)
        {
            this.ss = ss;
        }
         
        public void run()
        {
            char ch;
            for(int i=0; i<20; i++)
            {
                 ch = (char)('a'+i);
                
    ss.push(ch);




            }
        }
         
    }
     
    class consume implements Runnable
    {
        syncstack ss = null;
        public consume(syncstack ss)
        {
            this.ss =ss;
        }
        public void run()
        {
            for(int i=0; i<20; i++)
            {
               
    ss.pop();



                try
                {
                    Thread.sleep(500);
                 //this.wait();
                 //System.out.println("wwwwwwwwwwww");
                }
                catch(Exception e)
                {}
            }
        }
    }改后运行结果如下:
         生产了a
    当前容器共有1个物品
    生产了b
    当前容器共有2个物品
    生产了c
    当前容器共有3个物品
    生产了d
    当前容器共有4个物品
    生产了e
    当前容器共有5个物品
    生产了f
    当前容器共有6个物品
    消费了物品f
    当前还剩下5个物品
    消费了物品e
    当前还剩下4个物品
    消费了物品d
    当前还剩下3个物品
    消费了物品c
    当前还剩下2个物品
    消费了物品b
    当前还剩下1个物品
    消费了物品a
    当前还剩下0个物品
    call thread consume
    生产了g
    当前容器共有1个物品
    生产了h
    当前容器共有2个物品
    生产了i
    当前容器共有3个物品
    生产了j
    当前容器共有4个物品
    生产了k
    当前容器共有5个物品
    生产了l
    当前容器共有6个物品
    call produce thread
    消费了物品l
    当前还剩下5个物品
    消费了物品k
    当前还剩下4个物品
    消费了物品j
    当前还剩下3个物品
    消费了物品i
    当前还剩下2个物品
    消费了物品h
    当前还剩下1个物品
    消费了物品g
    当前还剩下0个物品
    call thread consume
    生产了m
    当前容器共有1个物品
    生产了n
    当前容器共有2个物品
    生产了o
    当前容器共有3个物品
    生产了p
    当前容器共有4个物品
    生产了q
    当前容器共有5个物品
    生产了r
    当前容器共有6个物品
    call produce thread
    消费了物品r
    当前还剩下5个物品
    消费了物品q
    当前还剩下4个物品
    消费了物品p
    当前还剩下3个物品
    消费了物品o
    当前还剩下2个物品
    消费了物品n
    当前还剩下1个物品
    消费了物品m
    当前还剩下0个物品
    call thread consume
    生产了s
    当前容器共有1个物品
    生产了t
    当前容器共有2个物品
    不过还存在一个问题,如果for循环结束了,而cnt条件不够就没有进入while循环当中唤醒另一根线程,那么还会出现商品数小于40的情况,所以最好是放在外面,而且最好是放在第一条语句当然,(你的数组长度与for循环次数成整数倍也可以)你的这个代码就出现了这种情况,你数一下商品数,只有38个,也就是当生产到38的时候,消费等待,而生产没有进入while循环唤醒消费,消费一直等待,生产则结束了.     
      

  4.   


    从你的这个示例来说,是可以非常好的演示 wait和notify/notifyAll 的用法,但上面的回复我认为是没有提到关键的地方的;从你的这个程序来看(你应该是明白了 wait和notify/notifyAll必须在同一个对象监视器上发生才行),有个条件cnt,你是通过这个条件来控制消费和生产的,所以只有这个条件满足时,消费或生产才能正常进行,从这里可以看出 wait() 和 notify()的作用:
    wait() 的作用是个将线程置入睡眠状态,同时又等待条件发生改变;
    notify()的作用是唤醒在此对象监视器上等待的单个线程;既然条件不满足时,线程立即要等待(调用wait()),那很显然,条件满足时,就应立即唤醒在此对象监视器上等待的线程了(notify/notifyAll);所以看下你的代码,你应该把notify()放在:
    push方法就是:data[cnt] = ch; cnt++; this.notify();
    pop()方法就是:ch = data[cnt - 1]; --cnt;this.notify();而不是你说的在while循环中了;
      

  5.   

    所以你若是清楚了怎么使用wait和notify,根本就不会陷入“把notify放在while循环里后只生产6个取出6个,然后两个线程都停滞了,为什么?”这样的问题了。