下面是生产者消费者的问题,我想问下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来完成上面的操作呢?
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来完成上面的操作呢?
楼主【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 %
值得尊敬
都是Object类的方法。任何对象类型都可以继承此两种方法。
至于红字没看到
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标签就愈发诡异了如果需要更进一步理解,得在本地编译运行一下。
重新贴下:
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来完成上面的操作呢?能否按照我上面提出的问题来回答下呢?
这个时候我是不是线程等待了(这里假设为线程A),释放了对象锁?然后要是有另外的线程B要是再进来了push方法,判断index != arrWT.length了,就执行了下面的notify()方法了,让上面的进程A解锁了???是不是这样的执行过程??????? 这里的线程B,其实就是消费线程,调用的notify()不是push()里面的,而是pop()里面的notify()来让A线程唤醒?
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 中,看看会出现什么问题
线程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,
。