重生之学Java的第十四天

一、生产者消费者模型

生产者消费者模型是一种并发编程模式,用于解决多线程环境下的数据共享和同步问题。在该模型中,有两类角色:生产者和消费者。

  • 生产者:负责生成或生产数据,并将其放入一个共享的缓冲区(也称为队列)中。生产者可以是一个线程或进程。
  • 消费者:负责从共享的缓冲区中获取数据,并对其进行处理或消耗。消费者可以是一个线程或进程。

以下是生产者消费者模型的基本工作流程:

  1. 创建一个共享的缓冲区作为交换数据的区域。
  2. 启动一个或多个生产者线程/进程,它们生成数据并将其放入缓冲区中。
  3. 启动一个或多个消费者线程/进程,它们从缓冲区中获取数据并进行处理。
  4. 当缓冲区为空时,消费者线程等待直到有数据可供消费。
  5. 当缓冲区已满时,生产者线程等待直到有空间可供放置数据。
  6. 生产者生成数据后,将其放入缓冲区,并唤醒任何等待中的消费者线程。
  7. 消费者从缓冲区获取数据后,对其进行处理,并唤醒任何等待中的生产者线程。

通过合理的同步机制(如互斥锁、条件变量等),生产者和消费者能够正确地协调工作,实现数据的有序生成和消费,避免数据竞争和死锁等并发问题。

生产者消费者模型在许多应用中都有广泛的应用,例如任务队列、消息队列、线程池等场景,可以有效地实现任务分配和资源利用的优化。

1、如何阻塞

  • 线程自己阻塞自己,也就是生产者、消费者各自调用wait()和notify().
  • 用一个阻塞队列,当获取不到或者放不进去的时候,入队、出队函数本身就是阻塞的。

2、如何实现双向通知

  • wait()和notify()
  • Condition机制

3、生产者消费者问题实现(wait和notify)

serviceImpl

public class KFCImpl implements IKFC {

    private Queue<Food> queue = new LinkedBlockingQueue<>();
    private final int MAX_SIZE = 10;

    @Override
    public synchronized void produce(String name) throws InterruptedException {
        if (queue.size() >= MAX_SIZE) {
            System.out.println("[生产者" + name + "] KFC生成达到上限,停止生成......");
            wait();
        } else {
            Food food = new Food("上校鸡块");
            queue.add(food);
            System.out.println("[生产者" + name + "] 生成一个:" + food.getName() + ",KFC有食物:" + queue.size() + "个");

            //唤醒等待的线程来消费
            notifyAll();
        }
    }

    @Override
    public synchronized void consume(String name) throws InterruptedException {
        if (queue.isEmpty()) {
            System.out.println("[消费者" + name + "] KFC食物已空,消费者停止消费......");
            wait();
        } else {
            Food food = queue.poll();
            System.out.println("[消费者" + name + "] 消费一个:" + food.getName() + ",KFC有食物:" + queue.size() + "个");

            //唤醒等待的线程来消费
            notifyAll();
        }
    }
}

Consumer

public class ConsumerThread extends  Thread{
    private IKFC kfc;
    public ConsumerThread(String name, IKFC kfc) {
        this.kfc = kfc;
    }

    @Override
    public void run() {
       while(true){
           try {
               kfc.consume(getName());
               sleep(300);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
    }
}

produce

public class ProduceThread extends  Thread{
    private IKFC kfc;
    public ProduceThread(String name,IKFC kfc) {
        super(name);
        this.kfc = kfc;
    }

    @Override
    public void run() {
       while(true){
           try {
               kfc.produce(getName());
               sleep(200);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值