多生产多消费
问题1:重复生产,重复消费
原因:被唤醒的线程没有判断标记就进行了生产或者消费,导致重复的生产与消费。
解决办法:就是被唤醒的线程必须先判断,while循环可以让被唤醒的线程再次进行标记判断。
问题2:唤醒以后出现了死锁
原因:本方线程使用notify()时有可能唤醒本方线程,本方线程循环判断标记之后,再次被wait(),导致所有线程全部进入冻结状态,没有就绪状态的线程存在,出现死锁。
解决方法:使用notifyAll()方法,每次都将线程池中的所有线程全部唤醒,不但唤醒本方,还唤醒了对方,虽然唤醒了本方,但是本方判断标记之后,继续wait(),这样对方线程就可以执行了。
package ProConDemo;
//创建共享资源
public class Goods {
private String name;
private int count = 1;
private boolean flag;
//创建一个生产方法
public synchronized void Sale(String name) {
while(flag)//线程只要被唤醒,就必须进行循环判断。
try {wait();} catch (InterruptedException e) {e.printStackTrace();}
this.name = name +"----"+count;
count++;
System.out.println(Thread.currentThread().getName()+"生产了"+this.name);
flag = true;//改变标记,让对方线程能够执行
notifyAll();//唤醒所有线程
}
//创建一个消费方法
public synchronized void Buy() {
while(!flag)//线程只要被唤醒,就必须进行循环判断。
try {wait();} catch (InterruptedException e) {e.printStackTrace();}
System.out.println(Thread.currentThread().getName()+"消费了"+this.name);
flag = false;//改变标记,让对方线程能够执行
notifyAll();//唤醒所有线程
}
}
package ProConDemo;
//创建线程任务----生产者
public class Pro implements Runnable{
private Goods good;
public Pro(Goods good) {
this.good = good;
}
public void run() {
while(true)
good.Sale("面包");
}
}
package ProConDemo;
//创建线程任务----消费者
public class Cou implements Runnable{
private Goods good;
public Cou(Goods good) {
this.good = good;
}
public void run() {
while(true)
good.Buy();
}
}
package ProConDemo;
public class Demo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Goods good = new Goods();
Pro pro = new Pro(good);
Cou cou = new Cou(good);
Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(cou);
Thread t3 = new Thread(cou);
t0.start();
t1.start();
t2.start();
t3.start();
}
}