java多线程 一个生产者和多个消费者

生产者和消费者模式是面试时很容易被问到的一类题,在平常的开发中也经常碰到,比如在网游开发中:用一个线程把收到的字节数据封装起来写到一个队列中,然后用一个或多个线程从该队列中把数据读取出来再分发。本文来实现类似的情景: 5个通宵加班并饿了一天的程序员去包子店吃小笼包,小笼包分为菜包和肉包,随机分配的,由于公司只给报销20个包子的钱,所以就只点了20个包子,包子店的老板娘一次只能蒸10个包子,而且是必须等他们吃完了蒸好的10个包子之后再继续做剩下的10个包子,由于这个世界本身是不公平的,所以抢的快的的就多吃点,但为了避免他们把包子抢烂,规定每次只能一个人去拿包子
这里生产者就是做包子的,消费者就是这5个饿晕了的coder,下面来看看怎么用代码实现它。
1. 创建包子店BreadShop.java,首先创建一些公用的数据
// 装包子的盘子
private ArrayList<Bread> breadList = new ArrayList<Bread>();
// 包子的种类:肉包和菜包
private BreadType breadTypes[] = { BreadType.MEAT, BreadType.VEGETABLES };
// 已经出炉的包子总数
private int totalCount = 0;
// 点的包子数
private final int MAX_COUNT = 20;
 
enum BreadType {
    MEAT, VEGETABLES
}
 
// 包子
class Bread {
    public BreadType type;
 
    public Bread(BreadType type) {
        this.type = type;
    }
}
2. 首先来了解一下代码中用到的几个方法:wait()、sleep()、notify()、notifyAll()
wait()和notify()以及notifyAll()是Object的方法,这三个方法跟锁有密切关系,必须写在synchronized代码块中。obj.wait()表示线程会释放对象obj的锁,处于等待状态,直到有其他线程调用obj对象的notify()或者notifyAll()函数,才有机会重新去竞争obj对象的锁。notify()和notifyAll()的区别:前者是唤醒等待池中的一个线程,然后系统会让它获得obj对象的锁;后者是唤醒所有等待该对象的线程,然后让它们去竞争obj对象的锁。虽然使用notify()或者notifyAll()都可以,但大多数情况下还是notifyAll()安全些,notify()可能由于一些代码缺陷出现死锁,特别是在一个生产者和多个消费者的模式中。
sleep()是Thread的函数,它指定线程休眠一段时间,但是不会释放对象的锁。
下面来实现生产者
class Product implements Runnable {
    private boolean isWork = false;
 
    public Product()
    {
        this.isWork = true;
    }
 
    // 把包子蒸熟后放到盘子里
    public void makeBread(Bread bread) {
        breadList.add(bread);
        switch(bread.type)
        {
        case MEAT:
            System.out.println("make a meat bread");
            break;
 
        case VEGETABLES:
            System.out.println("make a vegetables bread");
            break;
        }
    }
 
    @Override
    public void run() {
        while(isWork)
        {
            try {
                synchronized(breadList)
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用Java语言实现的生产者消费者模型的示例: ``` import java.util.LinkedList; public class ProducerConsumerExample { public static void main(String[] args) { LinkedList<Integer> queue = new LinkedList<>(); int maxSize = 5; Producer producer = new Producer(queue, maxSize); Consumer consumer = new Consumer(queue); Thread producerThread = new Thread(producer, "Producer"); Thread consumerThread = new Thread(consumer, "Consumer"); producerThread.start(); consumerThread.start(); } } class Producer implements Runnable { private LinkedList<Integer> queue; private int maxSize; public Producer(LinkedList<Integer> queue, int maxSize) { this.queue = queue; this.maxSize = maxSize; } @Override public void run() { while (true) { synchronized (queue) { while (queue.size() == maxSize) { try { System.out.println("队列已满,生产者等待消费..."); queue.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int number = (int) (Math.random() * 100); queue.add(number); System.out.println("生产者生产: " + number); queue.notifyAll(); } } } } class Consumer implements Runnable { private LinkedList<Integer> queue; public Consumer(LinkedList<Integer> queue) { this.queue = queue; } @Override public void run() { while (true) { synchronized (queue) { while (queue.isEmpty()) { try { System.out.println("队列为空,消费者等待生产..."); queue.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int number = queue.removeFirst(); System.out.println("消费者消费: " + number); queue.notifyAll(); } } } } ``` 上述代码实现了一个简单的生产者消费者模型,其中使用了一个线程安全的`LinkedList`队列作为生产者消费者之间的缓冲区。在`Producer`和`Consumer`类中,`run()`方法被覆盖并实现了生产和消费的逻辑。 在生产者线程中,如果队列已满,则生产者线程将进入等待状态。当队列不满时,生产者线程将生成随机数并将其添加到队列中,并通过调用`notifyAll()`方法通知消费者线程可以消费了。在消费者线程中,如果队列为空,则消费者线程将进入等待状态。当队列不为空时,消费者线程将从队列中删除第一个元素,并通过调用`notifyAll()`方法通知生产者线程可以继续生产。 这种实现方式使用`synchronized`关键字确保在对队列进行修改时线程安全。此外,生产者消费者线程之间的通信使用了`wait()`和`notifyAll()`方法,以确保生产者消费者之间的协调。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值