【多线程学习03】生产者消费者

本文通过一个Java程序实例展示了如何解决经典的生产者消费者问题。使用线程同步方法,包括wait()和notify(),来确保生产者在缓冲区满时不生产,消费者在缓冲区空时不消费,防止死锁。程序包括一个生产者线程和一个消费者线程,以及一个包含生产和消费同步方法的储物池类。
摘要由CSDN通过智能技术生成

        生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

        要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。 

package thread;

public class TestProducerConsumer {

    public static void main(String[] args) {

        Pool pool = new Pool();  //创建储物池
        Producer producer = new Producer(pool);  //创建生产者消费者对象
        Consumer consumer = new Consumer(pool);

        producer.start();  //开启线程
        consumer.start();

    }
}

class Producer extends Thread {  //生产者线程
    Pool pool = new Pool();

    public Producer(Pool pool) {
        this.pool = pool;
    }

    @Override
    public void run() {  //生产10个产品
        for (int i = 0; i < 10; i++) {
            pool.put(i);
        }
    }
}

class Consumer extends Thread {  //消费者线程
    Pool pool = new Pool();

    public Consumer(Pool pool) {
        this.pool = pool;
    }

    @Override
    public void run() {  //消费10个产品
        for (int i = 0; i < 10; i++) {
            pool.get();
        }
    }
}

class Pool{  //储物池类(包括生产和消费同步方法)
    private int id;
    private boolean flag = false;  //标志生产者生产是否完成(消费者是否完成消费)

    public synchronized void put(int id){  //生产同步方法,需放入生产出的产品id

        while (flag){  //消费者没完成消费
            try {
                wait();  //当前线程等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //消费者完成消费(flag == false)释放锁后生产者开始生产
        System.out.println("开始生产" + id);
        try {
            Thread.sleep((int)Math.random() * 100);  //随机数模拟生产耗时
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.id = id;
        System.out.println("结束生产" + id);

        flag = true;  //设置生产完成标志
        notify();  //唤醒等待队列中的线程(消费者)
    }

    public synchronized int get(){  //消费同步方法,返回消费产品id

        while(!flag){  //生产者还没完成生产
            try {
                wait();  //当前线程等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //生产者完成生产后消费者消费
        System.out.println("开始消费" + id);
        try {
            Thread.sleep((int)Math.random() * 100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束消费" + id);

        flag = false;  //提醒生产者生产
        notify();  //唤醒生产者
        return id;
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值