下面是生产者消费者的问题,我想问下public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
new Thread(p).start();
new Thread(c).start();
}
}class WoTou {
int id; 
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
}class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6];

public synchronized void push(WoTou wt) { //生产方法
while(index == arrWT.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
arrWT[index] = wt;
index ++;
}

public synchronized WoTou pop() {
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
index--;
return arrWT[index];
}
}class Producer implements Runnable {
SyncStack ss = null;
Producer(SyncStack ss) {
this.ss = ss;
}

public void run() {
for(int i=0; i<20; i++) {
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("生产了:" + wt);
try {
Thread.sleep((int)(Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}class Consumer implements Runnable {
SyncStack ss = null;
Consumer(SyncStack ss) {
this.ss = ss;
}

public void run() {
for(int i=0; i<20; i++) {
WoTou wt = ss.pop();
System.out.println("消费了: " + wt);
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}上面的红字部分不是启动了两个线程的?一个是生产的线程,一个是消费的线程?
启动之后分别执行其重写的run()方法,蓝色的字的部门
生产的速度比消费的速度快多了,然后黄色的字的部门,index == arrWT.length了,wait了
这个时候我是不是线程等待了(这里假设为线程A),释放了对象锁?然后要是有另外的线程B要是再进来了push方法,判断index != arrWT.length了,就执行了下面的notify()方法了,让上面的进程A解锁了???是不是这样的执行过程???????
先回答下上面的问题,还有个问题就是我只创建了一个生产线程,哪里会来两个生产线程A,B来完成上面的操作呢?

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【vstian】截止到2008-07-28 00:37:23的历史汇总数据(不包括此帖):
    发帖的总数量:25                       发帖的总分数:240                      每贴平均分数:9                        
    回帖的总数量:207                      得分贴总数量:120                      回帖的得分率:57%                      
    结贴的总数量:24                       结贴的总分数:240                      
    无满意结贴数:1                        无满意结贴分:20                       
    未结的帖子数:1                        未结的总分数:0                        
    结贴的百分比:96.00 %               结分的百分比:100.00%                  
    无满意结贴率:4.17  %               无满意结分率:8.33  %                  
    值得尊敬
      

  2.   

    wait() 是等待,notify()是唤醒...
      

  3.   

    wait()是线程暂停。notify()是线程唤醒。
    都是Object类的方法。任何对象类型都可以继承此两种方法。
    至于红字没看到
      

  4.   

    大概意思是创建一个空间,里边可以放6个WoTou对象。这个空间分别有两个方法push(WoTou wt),一个是生产一个是消费pop()。
    synchronized关键字代表互斥。就是说一个对象执行synchronized方法时,该对象被锁定,不可执行其他方法。
    换句话说。这两个方法(push,pop)只能同时执行一个。
    push方法会判断,当里边的WoTou已经装满(6个)的时候。该线程等待,暂停进行。否则将给序号(index)自加1。并且将push的对象放入数组中。
    pop方法同理。当里边已经空了的时候(0个)。该线程等待。否则的话,序号(index)自减1。并且将对象从数组中移除。除了空间,还创建了两个单独的线程。一个是生产线程,一个是消费线程。
    生产线程每200毫秒生产一个WoTou,并放入上述被创建的空间中(注意,最多只能放6个,超过6个会线程等待,如果等待,则要到少于6个为止)。即生产一个对象后,线程睡眠(sleep方法)0.2秒。
    消费线程每1000毫秒消费一个WoTou。并从空间中移除。大概只能理解到这样了,因为线程本身就不好理解,加上代码里还有color标签就愈发诡异了如果需要更进一步理解,得在本地编译运行一下。
      

  5.   

    不好意思 在代码框里面显示不了颜色
    重新贴下:
    public class ProducerConsumer {
        public static void main(String[] args) {
            SyncStack ss = new SyncStack();
            Producer p = new Producer(ss);
            Consumer c = new Consumer(ss);
            new Thread(p).start();
            new Thread(c).start();
        }
    }class WoTou {
        int id; 
        WoTou(int id) {
            this.id = id;
        }
        public String toString() {
            return "WoTou : " + id;
        }
    }class SyncStack {
        int index = 0;
        WoTou[] arrWT = new WoTou[6];
        
        public synchronized void push(WoTou wt) { //生产方法
            while(index == arrWT.length) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.notifyAll();        
            arrWT[index] = wt;
            index ++;
        }
        
        public synchronized WoTou pop() {
            while(index == 0) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.notifyAll();
            index--;
            return arrWT[index];
        }
    }class Producer implements Runnable {
        SyncStack ss = null;
        Producer(SyncStack ss) {
            this.ss = ss;
        }
        
        public void run() {
            for(int i=0; i<20; i++) {
                WoTou wt = new WoTou(i);
                ss.push(wt);
    System.out.println("生产了:" + wt);
                try {
                    Thread.sleep((int)(Math.random() * 200));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }            
            }
        }
    }class Consumer implements Runnable {
        SyncStack ss = null;
        Consumer(SyncStack ss) {
            this.ss = ss;
        }
        
        public void run() {
            for(int i=0; i<20; i++) {
                WoTou wt = ss.pop();
    System.out.println("消费了: " + wt);
                try {
                    Thread.sleep((int)(Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }            
            }
        }
    }
    上面的红字部分不是启动了两个线程的?一个是生产的线程,一个是消费的线程? 
    启动之后分别执行其重写的run()方法,蓝色的字的部门 
    生产的速度比消费的速度快多了,然后黄色的字的部门,index == arrWT.length了,wait了 
    这个时候我是不是线程等待了(这里假设为线程A),释放了对象锁?然后要是有另外的线程B要是再进来了push方法,判断index != arrWT.length了,就执行了下面的notify()方法了,让上面的进程A解锁了???是不是这样的执行过程??????? 
    先回答下上面的问题,还有个问题就是我只创建了一个生产线程,哪里会来两个生产线程A,B来完成上面的操作呢?能否按照我上面提出的问题来回答下呢?
      

  6.   

    难道是这样理解:
    这个时候我是不是线程等待了(这里假设为线程A),释放了对象锁?然后要是有另外的线程B要是再进来了push方法,判断index != arrWT.length了,就执行了下面的notify()方法了,让上面的进程A解锁了???是不是这样的执行过程??????? 这里的线程B,其实就是消费线程,调用的notify()不是push()里面的,而是pop()里面的notify()来让A线程唤醒?
      

  7.   

    是启动了两个线程,顺便创建了一个SyncStack实例用于存储WoTou是。这句话的意思是说空间满的时候,不能继续向里边push了。只能将此线程等待。对象锁释放。是的。因为A等待,所以执行B。因为index == arrWT.length 所以一定不能为0。所以执行notifyAll(); 于是A也被唤醒,但是由于此时B在占用对象(锁的)。所以A仍要等B执行完才可以继续。
      

  8.   

    你提出的是逻辑问题,仔细看看就明白。
    wait 和 notify 的使用和对应的加锁解锁的操作,才是重点。
    大家可以试试,把这个class SyncStack 内类给撤掉,int index = 0和 WoTou[] arrWT = new WoTou[6]放到主类中,即线程间以内类的方式进行通信,然后把这 public synchronized void push(WoTou wt)和  public synchronized WoTou pop() 方法分别放到
    两个方法放到class Producer和class Consumer 中,看看会出现什么问题
      

  9.   


    线程A:new Thread(p).start();
    线程B:new Thread(c).start();生产的速度比消费的速度快,
    当index == arrWT.length时,
    线程A会去执行this.wait();把SyncStack 类对象所拥有的锁给释放了,
    同时线程A等待。因为之前线程A把SyncStack 类对象的锁给占用了,线程B
    老是无法执行pop()方法(因为pop()方法前也有synchronized关键字,线程B必须拿到
    SyncStack 类对象的锁才可以执行pop()方法,但是这个锁之前是被线程A给占用了
    ) 此时线程A等待了,释放了锁,线程B终于可以拿到这把锁了,现在线程B可以执行pop()方法了,
    线程B在执行pop()方法时 ,会调用this.notifyAll();把线程A给唤醒,但尽管如此线程A并不能立刻
    就生产wotou了,因为锁此时还在线程B手上呢,所以线程B会继续的消费wotou的,但线程B只能消费一个wotou,
    因为在消费这个wotou之前,它调用了this.notifyAll();唤醒了线程A。
    所以当线程执行完pop()方法后,又会把锁释放,由线程A得到生产一个wotou。程序结果:线程A一直生产六个wotou,
    之后线程B消费一个wotou,
    线程A有生产一个wotou,