问题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(); } }
转载于:https://www.cnblogs.com/olddriver123/p/8250829.html
原文链接:https://blog.csdn.net/weixin_30342827/article/details/95773798
本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。
还没有人抢沙发呢~