public class Cangku {
private char[] ck;
private int count;
public Cangku(){
ck=new char[8];
count=0;
}
public synchronized void sc(char aa){
while(count==ck.length){
try {
this.wait();
} catch (Exception e) {
// TODO: handle exception
}
}
this.notify();
ck[count]=aa;
count++;
System.out.println(Thread.currentThread().getName()+"生产线正在生产第"+count+"个商品"+aa);
}
public synchronized void xf(){
while(count==0){
try {
this.wait();
} catch (Exception e) {
// TODO: handle exception
}
}
this.notify();
System.out.println(Thread.currentThread().getName()+"消费线正在消费第"+count--+"个商品"+ck[count]);
}
}
package 生产消费;
public class ShengChan implements Runnable {
private Cangku ck;
public ShengChan(Cangku ck) {
// TODO Auto-generated constructor stub
this.ck=ck;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<26;i++){
char aa=(char) ('A'+i);
ck.sc(aa);
}
}
}
package 生产消费;
public class Xiaofei implements Runnable {
private Cangku ck;
public Xiaofei(Cangku ck) {
// TODO Auto-generated constructor stub
this.ck=ck;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 26; i++) {
ck.xf();
}
}
}
package 生产消费;
public class Main {
public static void main(String[] args){
Cangku ck=new Cangku();
ShengChan sc=new ShengChan(ck);
Xiaofei xf=new Xiaofei(ck);
Thread thread1=new Thread(sc);
thread1.start();
Thread thread2=new Thread(xf);
thread2.start();
}
}
1.wait为什么要放在while循环中呢?
① 首先该程序涉及生产线程和消费线程,必须明白一点,线程的执行是由cpu随机分配的。
②还有线程有三个状态,等待,就绪,运行,起初定义线程的时候它属于就绪状态,所以只要得到cpu的分配就可以执行了。
③假设刚开始给消费线程分配了cpu,那么消费线程就可以从上到下执行代码,由于刚开始count=0所以进入while循环,执行了wait等待,此线程就不占有cpu了。
此时,cpu重新分配,由于消费线程处于等待状态,就算再次给它分配cpu也不会执行(因为等待状态下的线程除了得到cpu后,还有满足某种特定的条件才可以执行),而生产线程处于就绪状态(因为刚开始线程都处于就绪状态),当cpu给它分配线程时,它就可以立即执行(因为就绪状态下的 cpu只要得到cpu就可以执行了),生产线程由于此时count为0不等于8,所以不会执行while循环,它就执行了notify,该函数功能就是唤醒了另一个线程(注意不是本线程,而是另一个线程)这里只有消费和生产两个线程,只有消费处于等待状态,所以把它重新唤醒了,消费线程又重新进入就绪状态,得到cpu也就可以马上执行了,此时消费线程从上次进入wait的那个点继续执行,注意此时还没退出while循环,所以还要判断while(count==0),如果还等于零就又执行wait进入等待状态,如果不是就可以退出执行while循环外的代码,但是如果用if来判断只会执行一次,从上次wait那个点继续往下执行,它就不管是否 count=0这样就不是我们想要的效果了,所以这里把wait放在循环中起到在被唤醒还能再次判断一次条件后才能允许是否真的可以往下执行。
2.那notify为什么放在外面呢?
举一个极端的例子,当两个线程的notify也放在while循环里面而且放wait下面,那么当消费线程也是刚开始进入等待状态,停在了wait代码那里,此时生产线程拿到cpu,就执行,但是此时notify放在while循环里面,只有当count=8才能进去,但是就算满足条件进去了,是先执行wait,进入等待状态,而后面的notify根本没机会执行就进入等待状态了,那么这时生产线程和消费线程都处于等待状态,cpu分给哪个都不会执行,所以最后就会报错了。
以上纯属本人粗略的想法,有不对地方请指出,希望共同学习。