Java多线程_生产者消费者_包子铺_多生产多消费问题

本文通过一个包子店的场景,详细解释并展示了Java多线程中的生产者消费者问题。包括单生产者单消费者、单生产者多消费者、多生产者单消费者和多生产者多消费者的实现。代码示例中,生产者按需生产包子,消费者随机消费,同时确保了线程同步和等待唤醒机制的正确使用。
摘要由CSDN通过智能技术生成

生产者消费者问题

  1. 单生产单消费问题:
    • 将本例代码中生产者改为一个
    • 将本例代码中消费者改为一个
    • notifyAll()改为notify()也可正常工作
  2. 单生产多消费问题:
    • 将本例代码中生产者改为一个
  3. 多生产单消费问题
    • 将本例代码中消费者改为一个
  4. 多生产多消费问题
    • 如本例所示

包子店

生产者消费者模式

  1. 多个生产者(2个):
    • 包子店最多存放100个包子
    • 包子超过80个时,生产者等待wait()
    • 每当包子店包子少于80个时,会生产20个(一笼)包子,耗时3000ms;
    • 生产者每次生产包子后,notifyAll()
  2. 多个消费者(10个):
    • 每个消费者每隔一定时间(0~500ms)
    • 消费随机数目(1-5)的包子
    • 包子铺包子不够时,消费者等待wait()
    • 消费者每次消费包子后,notifyAll()

类图

包子类、包子铺类
消费者、生产者
客户端
包子铺类图

代码

包子类

public class StuffedBun {
}

包子铺类

public class BunShop {
    //最多有100个包子
    List<StuffedBun> list;

    public BunShop() {
        this.list = new ArrayList<>(100);
    }

    //生产者:包子数小于80,每3000ms生产20个包子
    public synchronized void producer() {
        while (true) {
            while (list.size() >= 80) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            for (int i = 0; i < 20; i++) {
                list.add(new StuffedBun());
            }
            System.out.printf("生产者%s生产了一批包子,目前包子店还剩%d个包子\n", Thread.currentThread().getName(), list.size());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.notifyAll();
        }
    }

    //消费者 每隔0~500ms  随机消费1-5个包子
    public synchronized void consumer() {
        while (true) {

            Random random = new Random();
            int num = random.nextInt(5) + 1;

            int seconds = random.nextInt(500) + 1;
            try {
                Thread.sleep(seconds);
                System.out.printf("消费者%s在%d毫秒后又来消费了\n", Thread.currentThread().getName(), seconds);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            while (list.size() < num) {
                try {
                    System.out.printf("目前包子店只有%d个包子,%s需要%d个包子;等待包子中\n", list.size(), Thread.currentThread().getName(), num);
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < num; i++) {
                list.remove(list.size() - 1);
            }
            //消费完 可能就缺包子了
            System.out.printf("消费者%s消费了%d个包子;目前包子店还剩%d个包子\n", Thread.currentThread().getName(), num, list.size());

            this.notifyAll();
        }
    }

}

生产者


public class Producer extends Thread {
    BunShop bunShop;

    public Producer(BunShop bunShop, String name) {
        this.bunShop = bunShop;
        this.setName(name);
    }

    @Override
    public void run() {
        bunShop.producer();
    }
}

消费者

public class Consumer extends Thread {
    BunShop bunShop ;

    public Consumer(BunShop bunShop,String name) {
        this.bunShop = bunShop;
        this.setName(name);
    }

    @Override
    public void run() {

        bunShop.consumer( );
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        BunShop bunShop = new BunShop();//创建一个最多容纳100包子的 包子铺
        //10个消费者线程
        for (int i = 1; i <= 10; i++) {
            new Consumer(bunShop, "consumer" + i).start();
        }
        //2个生产者线程
        for (int i = 1; i <= 2; i++) {
            new Producer(bunShop, "product" + i).start();
        }

    }
}

运行效果

/*
消费者consumer10在307毫秒后又来消费了
目前包子店只有0个包子,consumer10需要2个包子;等待包子中
消费者consumer9在358毫秒后又来消费了
目前包子店只有0个包子,consumer9需要4个包子;等待包子中
消费者consumer8在483毫秒后又来消费了
目前包子店只有0个包子,consumer8需要1个包子;等待包子中
生产者product2生产了一批包子,目前包子店还剩20个包子
生产者product2生产了一批包子,目前包子店还剩40个包子
生产者product2生产了一批包子,目前包子店还剩60个包子
生产者product2生产了一批包子,目前包子店还剩80个包子
...
目前包子店只有0个包子,consumer3需要5个包子;等待包子中
消费者consumer2在95毫秒后又来消费了
目前包子店只有0个包子,consumer2需要5个包子;等待包子中
目前包子店只有0个包子,consumer7需要5个包子;等待包子中
生产者product1生产了一批包子,目前包子店还剩20个包子
生产者product1生产了一批包子,目前包子店还剩40个包子
 */

部分笔试题实例

该部分面试题/笔试题实例来自 @ 几到多线程笔试题,有时间练练。

第六题:
生产者消费者问题:
这是一个非常经典的多线程题目,题目大意如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,所有生产者和消费者都是异步方式运行的,但它们必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经装满产品且尚未被取走的缓冲区中投放产品。

问题3-5解法见前一篇文章

问题7解法见后一篇文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值