java线程通信:同步代码块中执行wait和notify出错的问题

1,问题描述:

当使用同步代码块synchronized(Obj)代码块来解决生产者消费者问题时。出现了如下问题

2,下面是出错的完整代码:

代码中包含四个文件如下所示:

产品类:

生产者线程:

消费者线程:

测试类:

3,分析问题:

4,解决问题:

生产者和消费者线程都做如下改动,就可以了。

5,运行结果截图:


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的思路,在交流中成长,在总结中稳固江山。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值