0
点赞
收藏
分享

微信扫一扫

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

穆风1818 2022-02-04 阅读 103

        生产者消费者问题(英语: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 条评论