/**
*Title:ProducerConsumer_8
*Describtion:生产都消费问题,共有五个类,一个是主类,一个WoTou类,一个SyncStack类,一个生产者,一个消费者
熟悉同步机制中wait()和notify()的运用,对象数组的运用,及栈的表示方式。
*@Copyright:
*@Company:
*@author:firefly
*@version:1.0
*@time:2012.9.30
*/
public class ProducerConsumer_8 {
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(p).start();//也可以写多个生产者,只不过要在后面要用notifyAll();
//new Thread(p).start();
new Thread(c).start();
//new Thread(c).start();
//new Thread(c).start();
}
}
class WoTou {
int id;
WoTou(int id) {
this.id = id;
}
public String toString(){ //toString()这里是返回一个WoTou而不是打印一个WoTou.打印在类Consumer中表示。
return "WoTou :" + id; //+号两边要有空格的。
}
}
class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6];
public synchronized void push(WoTou wt){//synchronized应该在void之前而不是push前,而且必须用synchronizedc锁上。
while(index == arrWT.length) { //这里用while比用if好,若用if,则在wait的过程中,如果被打断,则就接着往下执行,产生错误。若用while即使产生了错误经过循环还是wait在那里。
try {
this.wait();//wait()是object类中的方法,它可以让在当前对象中运行的线程wait(),必须由notify()来叫醒它; 要写this.wait(),而不是wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
//this.notifyAll();
arrWT[index] = wt;
index++;
}
public synchronized WoTou pop() {
try {
while(index == 0){
this.wait();
}
} catch(InterruptedException e){
e.printStackTrace();
}
this.notify();
//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); //不要忘了WoTou要传入参数i;
ss.push(wt);
System.out.println("生产了:" + wt);
try {
Thread.sleep((int)(Math.random()) * 200); //每生产一个睡眠几秒钟,在for内写着。引入Math包,并要把double型的值强制转化为int型。
} 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(1000); //每消费一个睡眠1秒钟,在for内写着。
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}