本文转载自http://blog.csdn.net/evankaka
1、生产者仅仅在仓储未满时候生产,仓满则停止生产。
2、消费者仅仅在仓储有产品时候才能消费,仓空则等待。
3、当消费者发现仓储没产品可消费时候会通知生产者生产。
4、生产者在生产出可消费产品时候,应该通知等待的消费者去消费。
光看要求的话,应该不复杂。但是真正编程起来时,还是要考虑不少东西,本文将主要以三种方法来实现生产者-消费者模式:
一、wait/notify实现
这是一种比较常规的实现方法,但是代码个人感觉有点复杂。并且缺点是不能完全实现仓储有产品马上就消费。代码如下:
- package com.lin;
- import java.util.LinkedList;
- import java.util.List;
- class Storehouse {
- // 仓库的容量
- private int capacity;
- // object当成是生产的商品
- private List<Object> list = new LinkedList<Object>();
- public Storehouse(int capacity) {
- this.capacity = capacity;
- System.out.println("当前仓库产品数量:" + list.size());
- }
- public int getCapacity() {
- return capacity;
- }
- public void setCapacity(int capacity) {
- this.capacity = capacity;
- }
- /**
- * 生产的方法
- *
- * @throws InterruptedException
- */
- public void produrce(int num) throws InterruptedException {
- // 同步方法
- synchronized (list) {
- // 仓库还未满,且再生产num个产品不会超过仓库容量时可以生产产品
- while (list.size() + num > this.capacity) {
- // 仓库已满,或者放不下
- System.out.println("【仓库已无法再生产:" + num + "个产品】" + "当前仓库产品数量:" + list.size());
- list.wait();
- }
- System.out.println("【仓库还未满,生产:" + num + "个产品没有问题】" + "当前仓库产品数量:" + list.size());
- for (int i = 0; i < num; i++) {
- list.add(new Object());
- }
- list.notifyAll();
- }
- }
- /**
- * 消费
- *
- * @param num
- * @throws InterruptedException
- */
- public void consumer(int num) throws InterruptedException {
- // 同步方法
- synchronized (list) {
- // 仓库有没有num个产品可消费
- while (list.size() < num) {
- System.out.println("【仓库没有:" + num + "个产品可消费】" + "当前仓库产品数量:" + list.size());
- list.wait();
- }
- System.out.println("【仓库有:" + num + "个产品可消费】" + "当前仓库产品数量:" + list.size());
- for (int i = 0; i < num; i++) {
- list.remove(0);
- }
- list.notifyAll();
- }
- }
- }
- class ProducerThread extends Thread {
- // 每次生产的产品数量
- private int num;
- // 所在放置的仓库
- private Storehouse storehouse;
- // 构造函数,设置仓库
- public ProducerThread(Storehouse storehouse, int num) {
- this.storehouse = storehouse;
- this.num = num;
- }
- public void run() {
- try {
- storehouse.produrce(num);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- class ConsumerThread extends Thread {
- // 每次生产的产品数量
- private int num;
- // 所在放置的仓库
- private Storehouse storehouse;
- // 构造函数,设置仓库
- public ConsumerThread(Storehouse storehouse, int num) {
- this.storehouse = storehouse;
- this.num = num;
- }
- public void run() {
- try {
- storehouse.consumer(num);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public class Test1 {
- public static void main(String[] args) {
- // 仓库对象
- Storehouse storage = new Storehouse(1000);
- // 生产者对象
- ProducerThread p1 = new ProducerThread(storage, 200);
- ProducerThread p2 = new ProducerThread(storage, 200);
- ProducerThread p3 = new ProducerThread(storage, 100);
- ProducerThread p4 = new ProducerThread(storage, 300);
- ProducerThread p5 = new ProducerThread(storage, 400);
- ProducerThread p6 = new ProducerThread(storage, 200);
- ProducerThread p7 = new ProducerThread(storage, 500);
- // 消费者对象
- ConsumerThread c1 = new ConsumerThread(storage, 500);
- ConsumerThread c2 = new ConsumerThread(storage, 200);
- ConsumerThread c3 = new ConsumerThread(storage, 800);
- // 线程开始执行
- c1.start();
- c2.start();
- c3.start();
- p1.start();
- p2.start();
- p3.start();
- p4.start();
- p5.start();
- p6.start();
- p7.start();
- }
- }
输出结果:
- 当前仓库产品数量:0
- 【仓库没有:500个产品可消费】当前仓库产品数量:0
- 【仓库没有:800个产品可消费】当前仓库产品数量:0
- 【仓库还未满,生产:200个产品没有问题】当前仓库产品数量:0
- 【仓库没有:800个产品可消费】当前仓库产品数量:200
- 【仓库没有:500个产品可消费】当前仓库产品数量:200
- 【仓库还未满,生产:300个产品没有问题】当前仓库产品数量:200
- 【仓库有:500个产品可消费】当前仓库产品数量:500
- 【仓库没有:800个产品可消费】当前仓库产品数量:0
- 【仓库还未满,生产:200个产品没有问题】当前仓库产品数量:0
- 【仓库没有:800个产品可消费】当前仓库产品数量:200
- 【仓库有:200个产品可消费】当前仓库产品数量:200
- 【仓库没有:800个产品可消费】当前仓库产品数量:0
- 【仓库还未满,生产:200个产品没有问题】当前仓库产品数量:0
- 【仓库没有:800个产品可消费】当前仓库产品数量:200
- 【仓库还未满,生产:100个产品没有问题】当前仓库产品数量:200
- 【仓库没有:800个产品可消费】当前仓库产品数量:300
- 【仓库还未满,生产:400个产品没有问题】当前仓库产品数量:300
- 【仓库没有:800个产品可消费】当前仓库产品数量:700
- 【仓库已无法再生产:500个产品】当前仓库产品数量:700
二、lock实现
lock的实现其实和上面差不多,只不过还引入了lock,newCondition的条件,这是一个类似wait/notify的东西,用法也差不多。代码如下:
- package com.lin;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.concurrent.locks.Condition;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- class Storehouse {
- // 仓库的容量
- private int capacity;
- // object当成是生产的商品
- private List<Object> list = new LinkedList<Object>();
- // 锁
- private final Lock lock = new ReentrantLock();
- // 仓库满的条件变量
- private final Condition full = lock.newCondition();
- // 仓库空的条件变量
- private final Condition empty = lock.newCondition();
- public Storehouse(int capacity) {
- this.capacity = capacity;
- System.out.println("当前仓库产品数量:" + list.size());
- }
- public int getCapacity() {
- return capacity;
- }
- public void setCapacity(int capacity) {
- this.capacity = capacity;
- }
- /**
- * 生产的方法
- *
- * @throws InterruptedException
- */
- public void produrce(int num) throws InterruptedException {
- try {
- lock.lock();
- // 仓库还未满,且再生产num个产品不会超过仓库容量时可以生产产品
- while (list.size() + num > this.capacity) {
- // 仓库已满,或者放不下
- System.out.println("【仓库已无法再生产:" + num + "个产品】" + "当前仓库产品数量:" + list.size());
- empty.await();
- }
- System.out.println("【仓库还未满,生产:" + num + "个产品没有问题】" + "当前仓库产品数量:" + list.size());
- for (int i = 0; i < num; i++) {
- list.add(new Object());
- }
- full.signalAll();
- empty.signalAll();
- } finally {
- lock.unlock();
- }
- }
- /**
- * 消费
- *
- * @param num
- * @throws InterruptedException
- */
- public void consumer(int num) throws InterruptedException {
- try {
- lock.lock();
- // 仓库有没有num个产品可消费
- while (list.size() < num) {
- System.out.println("【仓库没有:" + num + "个产品可消费】" + "当前仓库产品数量:" + list.size());
- full.await();
- }
- System.out.println("【仓库有:" + num + "个产品可消费】" + "当前仓库产品数量:" + list.size());
- for (int i = 0; i < num; i++) {
- list.remove(0);
- }
- empty.signalAll();
- full.signalAll();
- } finally {
- lock.unlock();
- }
- }
- }
- class ProducerThread extends Thread {
- // 每次生产的产品数量
- private int num;
- // 所在放置的仓库
- private Storehouse storehouse;
- // 构造函数,设置仓库
- public ProducerThread(Storehouse storehouse, int num) {
- this.storehouse = storehouse;
- this.num = num;
- }
- public void run() {
- try {
- storehouse.produrce(num);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- class ConsumerThread extends Thread {
- // 每次生产的产品数量
- private int num;
- // 所在放置的仓库
- private Storehouse storehouse;
- // 构造函数,设置仓库
- public ConsumerThread(Storehouse storehouse, int num) {
- this.storehouse = storehouse;
- this.num = num;
- }
- public void run() {
- try {
- storehouse.consumer(num);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- public class Test2 {
- public static void main(String[] args) {
- // 仓库对象
- Storehouse storage = new Storehouse(1000);
- // 生产者对象
- ProducerThread p1 = new ProducerThread(storage, 200);
- ProducerThread p2 = new ProducerThread(storage, 200);
- ProducerThread p3 = new ProducerThread(storage, 100);
- ProducerThread p4 = new ProducerThread(storage, 300);
- ProducerThread p5 = new ProducerThread(storage, 400);
- ProducerThread p6 = new ProducerThread(storage, 200);
- ProducerThread p7 = new ProducerThread(storage, 500);
- // 消费者对象
- ConsumerThread c1 = new ConsumerThread(storage, 500);
- ConsumerThread c2 = new ConsumerThread(storage, 200);
- ConsumerThread c3 = new ConsumerThread(storage, 800);
- // 线程开始执行
- c1.start();
- c2.start();
- c3.start();
- p1.start();
- p2.start();
- p3.start();
- p4.start();
- p5.start();
- p6.start();
- p7.start();
- }
- }
- 当前仓库产品数量:0
- 【仓库没有:500个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库还未满,生产:200个产品没有问题】当前仓库产品数量:0
- 【仓库还未满,生产:100个产品没有问题】当前仓库产品数量:200
- 【仓库还未满,生产:500个产品没有问题】当前仓库产品数量:300
- 【仓库还未满,生产:200个产品没有问题】当前仓库产品数量:800
- 【仓库已无法再生产:300个产品】当前仓库产品数量:1000
- 【仓库已无法再生产:200个产品】当前仓库产品数量:1000
- 【仓库有:500个产品可消费】当前仓库产品数量:1000
- 【仓库有:200个产品可消费】当前仓库产品数量:500
- 【仓库还未满,生产:400个产品没有问题】当前仓库产品数量:300
- 【仓库没有:800个产品可消费】当前仓库产品数量:700
- 【仓库还未满,生产:300个产品没有问题】当前仓库产品数量:700
- 【仓库已无法再生产:200个产品】当前仓库产品数量:1000
- 【仓库有:800个产品可消费】当前仓库产品数量:1000
- 【仓库还未满,生产:200个产品没有问题】当前仓库产品数量:200
三、BlockingQueue实现
BlockingQueue是阻塞队列,可以实现入队阻塞、取数阻塞。对于生产者-消费者很适用,而且可以实现一有产品就可以马上就进行消费。不用像上面的两种方法都等到仓库生产足够的产品后才进行消费。而且代码量也不多,容易理解,代码如下:
- package com.lin;
- import java.util.concurrent.ArrayBlockingQueue;
- import java.util.concurrent.BlockingQueue;
- import java.util.concurrent.atomic.AtomicInteger;
- class Storehouse {
- // 仓库的容量
- private int capacity;
- // 仓库存储的载体
- private BlockingQueue<Object> blockingQueue;
- // 当前个数
- private AtomicInteger curNum = new AtomicInteger(0);
- public Storehouse(int capacity) {
- this.capacity = capacity;
- this.blockingQueue = new ArrayBlockingQueue<Object>(capacity);
- }
- /**
- * 生产的方法
- *
- * @throws InterruptedException
- */
- public void produrce(int num) {
- while (num + curNum.get() > capacity) {
- System.out.println("【仓库已无法再生产:" + num + "个产品】" + "当前仓库产品数量:" + curNum.get());
- }
- System.out.println("【仓库还未满,生产:" + num + "个产品没有问题】" + "当前仓库产品数量:" + blockingQueue.size());
- for (int i = 0; i < num; i++) {
- blockingQueue.add(new Object());
- curNum.incrementAndGet();
- }
- }
- /**
- * 消费
- *
- * @param num
- * @throws InterruptedException
- */
- public void consumer(int num) {
- while (num > curNum.get()) {
- System.out.println("【仓库没有:" + num + "个产品可消费】" + "当前仓库产品数量:" + blockingQueue.size());
- }
- System.out.println("【仓库有:" + num + "个产品可消费】" + "当前仓库产品数量:" + blockingQueue.size());
- for (int i = 0; i < num; i++) {
- try {
- blockingQueue.take();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- curNum.decrementAndGet();
- }
- }
- }
- class ProducerThread extends Thread {
- // 每次生产的产品数量
- private int num;
- // 所在放置的仓库
- private Storehouse storehouse;
- // 构造函数,设置仓库
- public ProducerThread(Storehouse storehouse, int num) {
- this.storehouse = storehouse;
- this.num = num;
- }
- public void run() {
- storehouse.produrce(num);
- }
- }
- class ConsumerThread extends Thread {
- // 每次生产的产品数量
- private int num;
- // 所在放置的仓库
- private Storehouse storehouse;
- // 构造函数,设置仓库
- public ConsumerThread(Storehouse storehouse, int num) {
- this.storehouse = storehouse;
- this.num = num;
- }
- public void run() {
- storehouse.consumer(num);
- }
- }
- public class Test3 {
- public static void main(String[] args) {
- // 仓库对象
- Storehouse storage = new Storehouse(1000);
- // 生产者对象
- ProducerThread p1 = new ProducerThread(storage, 200);
- ProducerThread p2 = new ProducerThread(storage, 200);
- ProducerThread p3 = new ProducerThread(storage, 100);
- ProducerThread p4 = new ProducerThread(storage, 300);
- ProducerThread p5 = new ProducerThread(storage, 400);
- ProducerThread p6 = new ProducerThread(storage, 200);
- ProducerThread p7 = new ProducerThread(storage, 500);
- // 消费者对象
- ConsumerThread c1 = new ConsumerThread(storage, 500);
- ConsumerThread c2 = new ConsumerThread(storage, 200);
- ConsumerThread c3 = new ConsumerThread(storage, 800);
- // 线程开始执行
- c1.start();
- c2.start();
- c3.start();
- p1.start();
- p2.start();
- p3.start();
- p4.start();
- p5.start();
- p6.start();
- p7.start();
- }
- }
- 【仓库没有:500个产品可消费】当前仓库产品数量:0
- 【仓库没有:500个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库还未满,生产:200个产品没有问题】当前仓库产品数量:0
- 【仓库还未满,生产:200个产品没有问题】当前仓库产品数量:1
- 【仓库没有:500个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:0
- 【仓库没有:200个产品可消费】当前仓库产品数量:39
- 【仓库还未满,生产:300个产品没有问题】当前仓库产品数量:39
- 【仓库还未满,生产:100个产品没有问题】当前仓库产品数量:113
- 【仓库没有:800个产品可消费】当前仓库产品数量:0
- 【仓库还未满,生产:200个产品没有问题】当前仓库产品数量:165
- 【仓库没有:200个产品可消费】当前仓库产品数量:39
- 【仓库有:200个产品可消费】当前仓库产品数量:273
- 【仓库没有:500个产品可消费】当前仓库产品数量:39
- 【仓库没有:500个产品可消费】当前仓库产品数量:327
- 【仓库没有:500个产品可消费】当前仓库产品数量:327
- 【仓库没有:500个产品可消费】当前仓库产品数量:327
- 【仓库还未满,生产:400个产品没有问题】当前仓库产品数量:327
- 【仓库没有:800个产品可消费】当前仓库产品数量:327
- 【仓库没有:500个产品可消费】当前仓库产品数量:327
- 【仓库没有:800个产品可消费】当前仓库产品数量:479
- 【仓库没有:800个产品可消费】当前仓库产品数量:497
- 【仓库没有:500个产品可消费】当前仓库产品数量:516
- 【仓库有:500个产品可消费】当前仓库产品数量:516
- 【仓库还未满,生产:500个产品没有问题】当前仓库产品数量:506
- 【仓库没有:800个产品可消费】当前仓库产品数量:558
- 【仓库没有:800个产品可消费】当前仓库产品数量:558
- 【仓库没有:800个产品可消费】当前仓库产品数量:558
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:568
- 【仓库没有:800个产品可消费】当前仓库产品数量:567
- 【仓库没有:800个产品可消费】当前仓库产品数量:557
- 【仓库没有:800个产品可消费】当前仓库产品数量:607
- 【仓库没有:800个产品可消费】当前仓库产品数量:710
- 【仓库没有:800个产品可消费】当前仓库产品数量:727
- 【仓库没有:800个产品可消费】当前仓库产品数量:719
- 【仓库没有:800个产品可消费】当前仓库产品数量:719
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:760
- 【仓库没有:800个产品可消费】当前仓库产品数量:769
- 【仓库有:800个产品可消费】当前仓库产品数量:835