java Lock-condition 模拟生产者消费者模式


/**
 * Condition putCondition = lock.newCondition();//实例
 * putCondition.await();//与Object.wait方法一样,都是要与while共同使用,使线程等待,释放锁,
                          直到putCondition.signal()或putCondition.signalAll()才继续执行
 * putCondition.signal();//唤醒 putCondition.await() 等待的线程
 *
 *  Lock 的 condition 进行 模拟 生产者和消费者 模式
 *  模拟 生产者 的仓库最大是3,大于3之后,只有等消费者消费完后才能进行生产
 *  消费者需要等仓库有东西之后,才能进行消费
 */
public class LockConditionTest {
    Lock lock = new ReentrantLock();
    private Condition putCondition = lock.newCondition();
    private Condition popCondition = lock.newCondition();

    private List<Integer> dataList = new ArrayList<>();//仓库

    /**
     * 生产者方法
     */
    public void put(){
        try {
            lock.lock();
            while (dataList.size() >= 3){
                System.out.println("仓库数量超过3,不能进行生产 size:"+dataList.size());
                putCondition.await();
                System.out.println("生产者被唤醒");
            }
            dataList.add(dataList.size() + 1);
            System.out.println("生产者生产 1 个商品,当前 仓库 size:"+dataList.size());
            popCondition.signalAll();//通知消费者 消费
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    /**
     * 消费者方法
     */
    public void pop(){
        try {
            lock.lock();
            while (dataList.size() == 0 ){
                System.out.println("仓库无商品,不能进行消费 size:"+dataList.size());
                popCondition.await();
                System.out.println("消费者被唤醒");
            }
            dataList.remove(0);
            System.out.println("消费者消费1个商品,当前 仓库 size:"+dataList.size());
            putCondition.signalAll();//通知生产者生产
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        LockConditionTest test = new LockConditionTest();
        //生产者线程 1
        new Thread(()->{
            while (true) {
                try {
                    Thread.sleep(1000);
                    test.put();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        //生产者线程 2
        new Thread(()->{
            while (true) {
                try {
                    Thread.sleep(1000);
                    test.put();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        //消费者线程 1
        new Thread(()->{
            while (true) {
                try {
                    Thread.sleep(2000);
                    test.pop();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        //消费者线程 2
        new Thread(()->{
            while (true) {
                try {
                    Thread.sleep(2000);
                    test.pop();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

 

运行结果:

生产者生产 1 个商品,当前 仓库 size:1
生产者生产 1 个商品,当前 仓库 size:2
消费者消费1个商品,当前 仓库 size:1
消费者消费1个商品,当前 仓库 size:0
生产者生产 1 个商品,当前 仓库 size:1
生产者生产 1 个商品,当前 仓库 size:2
生产者生产 1 个商品,当前 仓库 size:3
仓库数量超过3,不能进行生产 size:3
消费者消费1个商品,当前 仓库 size:2
消费者消费1个商品,当前 仓库 size:1
生产者被唤醒
生产者生产 1 个商品,当前 仓库 size:2
生产者生产 1 个商品,当前 仓库 size:3
仓库数量超过3,不能进行生产 size:3
仓库数量超过3,不能进行生产 size:3
消费者消费1个商品,当前 仓库 size:2
消费者消费1个商品,当前 仓库 size:1
生产者被唤醒

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产者-消费者问题是一个经典的同步问题,它描述了多线程/进程之间共享缓冲区时可能遇到的问题。在本文中,我将介绍如何在 Linux 下模拟实现生产者-消费者问题。 生产者-消费者问题的场景如下:有一个缓冲区,生产者向缓冲区中放置数据,而消费者从缓冲区中取走数据。生产者和消费者之间要进行同步,以避免以下问题: 1. 缓冲区溢出:如果生产者往缓冲区中放置数据时,缓冲区已经满了,那么生产者需要等待,直到消费者取走了一些数据,腾出了缓冲区。 2. 缓冲区下溢:如果消费者想从缓冲区中取数据,但是缓冲区已经空了,那么消费者需要等待,直到生产者放置了一些数据,填满了缓冲区。 为了解决这些问题,我们需要使用互斥锁和条件变量。互斥锁用于保护缓冲区,以避免多个线程同时访问缓冲区。条件变量用于通知其他线程缓冲区已经被修改或者缓冲区可以被修改。 下面是一个简单的生产者-消费者问题的模拟实现: ```c #include <stdio.h> #include <pthread.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int buffer_index; pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t buffer_cond_producer = PTHREAD_COND_INITIALIZER; pthread_cond_t buffer_cond_consumer = PTHREAD_COND_INITIALIZER; void *producer(void *arg) { for(int i = 0; i < 50; i++) { pthread_mutex_lock(&buffer_mutex); if(buffer_index == BUFFER_SIZE) { // 缓冲区已满,等待消费消费 pthread_cond_wait(&buffer_cond_producer, &buffer_mutex); } buffer[buffer_index] = i; buffer_index++; printf("生产者生产:%d\n", i); // 通知消费者缓冲区已经被修改 pthread_cond_signal(&buffer_cond_consumer); pthread_mutex_unlock(&buffer_mutex); } return NULL; } void *consumer(void *arg) { for(int i = 0; i < 50; i++) { pthread_mutex_lock(&buffer_mutex); if(buffer_index == 0) { // 缓冲区已空,等待生产者生产 pthread_cond_wait(&buffer_cond_consumer, &buffer_mutex); } int item = buffer[buffer_index-1]; buffer_index--; printf("消费消费:%d\n", item); // 通知生产者缓冲区已经被修改 pthread_cond_signal(&buffer_cond_producer); pthread_mutex_unlock(&buffer_mutex); } return NULL; } int main() { pthread_t producer_thread, consumer_thread; pthread_create(&producer_thread, NULL, producer, NULL); pthread_create(&consumer_thread, NULL, consumer, NULL); pthread_join(producer_thread, NULL); pthread_join(consumer_thread, NULL); return 0; } ``` 在上面的例子中,我们使用了三个线程:一个主线程和一个生产者线程和一个消费者线程。主线程用于启动生产者和消费者线程,并等待它们完成。生产者线程负责向缓冲区中放置数据,消费者线程负责从缓冲区中取走数据。 我们使用一个数组 buffer 来表示缓冲区,一个整数 buffer_index 来表示缓冲区中元素的数量。我们还使用了三个互斥锁和两个条件变量: - buffer_mutex:用于保护缓冲区。 - buffer_cond_producer:当生产者放置数据到缓冲区中时,通知消费者缓冲区已经被修改。 - buffer_cond_consumer:当消费者从缓冲区中取数据时,通知生产者缓冲区已经被修改。 在生产者线程中,我们使用了 while 循环来不断地向缓冲区中放置数据。如果缓冲区已满,那么生产者线程会等待消费者线程消费数据,直到缓冲区有空间可以放置数据。在放置数据之后,生产者线程会通知消费者线程缓冲区已经被修改。 在消费者线程中,我们使用了 while 循环来不断地从缓冲区中取数据。如果缓冲区已空,那么消费者线程会等待生产者线程放置数据,直到缓冲区中有数据可以被取走。在取走数据之后,消费者线程会通知生产者线程缓冲区已经被修改。 在主线程中,我们使用 pthread_join 函数等待生产者线程和消费者线程完成。 以上就是一个简单的生产者-消费者问题的模拟实现。在实际应用中,生产者和消费者可能会是不同的进程,但是解决问题的方法是相同的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值