Java多线程系列(十一)Java使用多线程实现生产者,消费者(wait,notify)

13 篇文章 0 订阅

首先:引用wiki百科的定义

链接:

https://zh.wikipedia.org/wiki/%E7%94%9F%E4%BA%A7%E8%80%85%E6%B6%88%E8%B4%B9%E8%80%85%E9%97%AE%E9%A2%98#Java_%E4%B8%AD%E7%9A%84%E4%BE%8B%E5%AD%90

生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多进程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个进程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。

生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。

该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。

同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。

========================================================

总结一下要点:

1.缓冲区的大小固定

2.生产者在缓冲区满时休眠,下次消费者小号缓冲区中的数据的时候生产者才被唤醒

3.消费者在缓冲区空时休眠,等到生产者往缓冲区加入数据后,再唤醒

----------------------------

下面是生产者消费者模式的简单实现:

final int addSpeed = 1000;
final int removeSpeed = 2000;
Thread thread1;
Thread thread2;
thread1 = new Thread(new Runnable() {
    @Override
    public void run() {
        while (true) {
            //生产者
            Random random = new Random();
            random.nextInt(1000);
            try {
                Thread.sleep(random.nextInt(1000) + addSpeed);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            doAdd();
        }
    }
});

thread1.start();
thread2 = new Thread(new Runnable() {
    @Override
    public void run() {
        //消费者
        while (true) {
            Random random = new Random();
            random.nextInt(1000);
            try {
                Thread.sleep(random.nextInt(1000) + removeSpeed);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            doRemove();
        }
    }
});
thread2.start();
//消费
private void doRemove() {
    synchronized (lock1) {
        if (mStringList.size() <= 0) {
            try {
                lock1.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        } else {
            int size1 = mStringList.size();
            mStringList.remove(0);
            Log.i(TAG, "取Object 取之前Size " + size1+ "取完后Size" + mStringList.size());
            lock1.notify();
        }
    }
}

private int queueSize = 8;

//生产
private void doAdd() {
    synchronized (lock1) {
        if (mStringList.size() >= queueSize) {
            try {
                lock1.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {

            int size1 = mStringList.size();
            mStringList.add("");
            Log.i(TAG, "AddObject,Add之前" +size1+"add 之后"+ mStringList.size());
            lock1.notify();
        }
    }
}

---------------------------------------------

因为:每次Add或者或者remove的时候都会notify一下,

这样当queue为空的时候 消费者wait,只要生产者Add了,消费者就会被唤醒

同理,当queue满了的时候 生产者wait,只要消费者remove了,生产者就会被唤醒

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值