当使用同步代码块synchronized(Obj)代码块来解决生产者消费者问题时。出现了如下问题
1,问题描述:
当使用同步代码块synchronized(Obj)代码块来解决生产者消费者问题时。出现了如下问题
2,下面是出错的完整代码:
代码中包含四个文件如下所示:
产品类:
package com.wyqxjw.test01; /** * @Auther: yqwang * @Date: 2021/4/7 * @Description: com.wyqxjw.test01 * @version: 1.0 */ //产品类(供消费者消费,生产者生产) public class Product { private String brand;//品牌 private String name;//产品名 public boolean flag = false;//一个信号,当为false时,意味着仓库里没产品,消费者需要等待,生产者可以生产。否则相反 public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Product(String brand, String name) { this.brand = brand; this.name = name; } public Product() { } }
生产者线程:
package com.wyqxjw.test01;
/**
* @Auther: yqwang
* @Date: 2021/4/7
* @Description: com.wyqxjw.test01
* @version: 1.0
*/
public class ProducerThread extends Thread{
Product p;
public ProducerThread(Product p){
this.p = p;
}
@Override
public void run() {
for (int i=0; i<20; i++) {
synchronized (p) {
if (p.flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (i % 2 == 0) {
p.setBrand("费列罗");
p.setName("巧克力");
} else {
p.setBrand("哈尔滨");
p.setName("啤酒");
}
System.out.println("我是生产者,我生产了" + p.getBrand() + "-----" + p.getName());
p.flag = true;
notify();
}
}
}
}
消费者线程:
package com.wyqxjw.test01;
/**
* @Auther: yqwang
* @Date: 2021/4/7
* @Description: com.wyqxjw.test01
* @version: 1.0
*/
public class ConsumerThread extends Thread{
Product p;
public ConsumerThread(Product p){
this.p = p;
}
@Override
public void run() {
for (int i=0; i<20; i++){
synchronized (p){
if (!p.flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("我是消费者,我消费了"+p.getBrand()+"-------"+p.getName());
p.flag = false;
notify();
}
}
}
}
测试类:
package com.wyqxjw.test01;
/**
* @Auther: yqwang
* @Date: 2021/4/7
* @Description: com.wyqxjw.test01
* @version: 1.0
*/
public class Test {
public static void main(String[] args) {
Product p = new Product();
ProducerThread pt = new ProducerThread(p);
ConsumerThread ct = new ConsumerThread(p);
pt.start();
ct.start();
}
}
3,分析问题:
4,解决问题:
生产者和消费者线程都做如下改动,就可以了。
5,运行结果截图:
参考资料:https://blog.youkuaiyun.com/coding_1994/article/details/80634792(感谢这个文章的作者和翔哥,提供了改bug的思路,在交流中成长,在总结中稳固江山。)