生产者消费者模式,以及基于BlockingQueue的快速实现

我爱普洱茶  金牌会员 | 2024-8-27 19:24:58 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 860|帖子 860|积分 2580

生产者消费者模式,以及基于BlockingQueue的快速实现
什么是生产者消费者模式,
简单来说就是有两个角色,一个角色重要负责生产数据,一个角色重要负责消费(使用)数据。
那么生产者直接依赖消费者,然后直接调用是否可以?
答案是可以的,但是有些场景无法实时解决,典范的就是生产者消费者的速率无法同步,导致整体的速率上不去的环境。实行速率永久取决于二者的最小速率(假设生产者和消费者的速率时快时慢)。
一样平常的解决方案是什么呢?
我们通常会加一个中间件,作为缓冲队列。
生产者生产好的数据丢到缓冲队列中,消费者根据自身环境实时获取数据,处理数据,如下图:

典范的实现就是Mq,比如Rocket mq、rabbit mq等,这是微服务、分布式场景下一个常见的中间件。
在服务内部,我们通常也会出现生产者消费者的模式,这时候引入mq显然有一些过重,我们需要更高效,更简洁的办法。
最简单的办法就是用一个queue,或者用一个List,生产者从队尾增加数据,消费者从队列头部取数据。
但是如许就会存在多线程共享数据的场景,需要做一些锁来解决线程同步的题目。
其次我们消费者在抢占数据时,我们又盼望有公平抢占和非公平抢占锁的题目,
同时我们还要思量缓冲队列是否要有界,如果无界的话,资源是否会存在耗尽题目,
而且我们还要思量是否可以更优雅的平衡生产者和消费者的处理速率,比如:
如使用线程状态来控制,
如果缓冲队列满了,那么生产者自己会挂起停止生产,当队列有空余空间时(注意不是全部清空数据),生产者会被唤醒继续生产;
如果缓冲队列空了,那么消费者自己会挂起停止消费,当队列有数据时(注意不是全部堆满数据),消费者会被唤醒继续消费。
诸如此类等等题目,如果我们想开发如许一个缓冲队列,要思量和解决还是比力有难度的。
而java8 提供的工具包早已看穿了这一切,(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )并提供了一套优雅的解决方案BlockingQueue
BlockingQueue 是一个接口界说,我们实际使用的是下边的各个实现类:

BlockingQueue 中常用的方法如下:

除此之外还会有获取指定元素(不移除)E element()/E peek(),删除指定元素boolean remove(Object o)等方法这里就先不赘述了。
下面我们来看一组简单的示例
生产者生产三种礼物gift: 手机/电脑/LV包
消费者通通消费
生产者消费者都使用线程池来维护,具体环境如下代码:
主类
  1. 1 package com.example.demo.learnblockingqueue;
  2. 2
  3. 3 import java.util.Comparator;
  4. 4 import java.util.concurrent.ArrayBlockingQueue;
  5. 5 import java.util.concurrent.BlockingQueue;
  6. 6 import java.util.concurrent.DelayQueue;
  7. 7 import java.util.concurrent.ExecutorService;
  8. 8 import java.util.concurrent.Executors;
  9. 9 import java.util.concurrent.LinkedBlockingQueue;
  10. 10 import java.util.concurrent.PriorityBlockingQueue;
  11. 11 import java.util.concurrent.SynchronousQueue;
  12. 12
  13. 13 /**
  14. 14  * @discription
  15. 15  */
  16. 16 public class BlockQueueMain {
  17. 17     public static void main(String[] args) {
  18. 18
  19. 19         BlockingQueue<Gift> queue = new ArrayBlockingQueue<>(3);
  20. 20         Gift phone = new Gift("iphone", 8888);
  21. 21         Producer phoneProducer = new Producer(queue, "AAAA  苹果代工厂", phone);
  22. 22
  23. 23         Gift computer = new Gift("lenovo", 12888);
  24. 24         Producer computerProducer = new Producer(queue, "AAAA  联想代工厂", computer);
  25. 25
  26. 26         Gift bag = new Gift("LV", 28888);
  27. 27         Producer bagProducer = new Producer(queue, "AAAA  LV代工厂", bag);
  28. 28
  29. 29         Consumer zConsumer = new Consumer(queue, "BBBB  小Z");
  30. 30         Consumer lConsumer = new Consumer(queue, "BBBB  小L");
  31. 31
  32. 32         ExecutorService executorService = Executors.newCachedThreadPool();
  33. 33         executorService.submit(phoneProducer);
  34. 34         executorService.submit(computerProducer);
  35. 35         executorService.submit(bagProducer);
  36. 36         executorService.submit(zConsumer);
  37. 37         executorService.submit(lConsumer);
  38. 38
  39. 39     }
  40. 40 }
复制代码
产品类
  1. 1 package com.example.demo.learnblockingqueue;
  2. 2
  3. 3 import lombok.AllArgsConstructor;
  4. 4 import lombok.Data;
  5. 5 import lombok.NoArgsConstructor;
  6. 6
  7. 7 import java.util.Date;
  8. 8 import java.util.concurrent.Delayed;
  9. 9 import java.util.concurrent.TimeUnit;
  10. 10
  11. 11 /**
  12. 12  * @discription
  13. 13  */
  14. 14 @Data
  15. 15 @NoArgsConstructor
  16. 16 public class Gift implements Delayed {
  17. 17
  18. 18     private String name;
  19. 19
  20. 20     private int price;
  21. 21
  22. 22     private final long completeTime = new Date().getTime() + 3000;
  23. 23
  24. 24     public Gift(Gift giftSample) {
  25. 25         name = giftSample.getName();
  26. 26         price = giftSample.getPrice();
  27. 27     }
  28. 28
  29. 29     public Gift(String name, int price) {
  30. 30         this.name = name;
  31. 31         this.price = price;
  32. 32     }
  33. 33
  34. 34     @Override
  35. 35     public long getDelay(TimeUnit unit) {
  36. 36
  37. 37         return unit.convert(completeTime - new Date().getTime(), TimeUnit.MILLISECONDS);
  38. 38     }
  39. 39
  40. 40     @Override
  41. 41     public int compareTo(Delayed o) {
  42. 42         return 0;
  43. 43     }
  44. 44 }
复制代码
生产者:
  1. 1 package com.example.demo.learnblockingqueue;
  2. 2
  3. 3 import lombok.extern.slf4j.Slf4j;
  4. 4
  5. 5 import java.util.concurrent.BlockingQueue;
  6. 6 import java.util.concurrent.TimeUnit;
  7. 7
  8. 8 /**
  9. 9  * @discription
  10. 10  */
  11. 11 @Slf4j
  12. 12 public class Producer implements Runnable {
  13. 13
  14. 14     private final BlockingQueue<Gift> queue;
  15. 15
  16. 16     private final String name;
  17. 17
  18. 18     private final Gift giftSample;
  19. 19
  20. 20     public Producer(BlockingQueue<Gift> queue, String name, Gift giftSample) {
  21. 21         this.queue = queue;
  22. 22         this.name = name;
  23. 23         this.giftSample = giftSample;
  24. 24     }
  25. 25
  26. 26     @Override
  27. 27     public void run() {
  28. 28
  29. 29         while (true) {
  30. 30             Gift newGift = new Gift(giftSample);
  31. 31             try {
  32. 32                 log.warn(name + "开始生产:{}", newGift);
  33. 33                 queue.put(newGift);
  34. 34                 log.warn(name + "生产了:{}, 剩余空间{}", newGift,  queue.remainingCapacity());
  35. 35
  36. 36                 TimeUnit.MILLISECONDS.sleep(10000);
  37. 37             } catch (InterruptedException e) {
  38. 38                 log.error("producer  {} catch a ex", name, e);
  39. 39             }
  40. 40         }
  41. 41     }
  42. 42 }
复制代码
消费者:
  1. 1 package com.example.demo.learnblockingqueue;
  2. 2
  3. 3 import lombok.extern.slf4j.Slf4j;
  4. 4
  5. 5 import java.util.concurrent.BlockingQueue;
  6. 6 import java.util.concurrent.TimeUnit;
  7. 7
  8. 8 /**
  9. 9  * @discription
  10. 10  */
  11. 11 @Slf4j
  12. 12 public class Consumer implements Runnable {
  13. 13
  14. 14     private final String name;
  15. 15     private final BlockingQueue<Gift> queue;
  16. 16
  17. 17
  18. 18     public Consumer(BlockingQueue<Gift> queue, String name) {
  19. 19         this.queue = queue;
  20. 20         this.name = name;
  21. 21     }
  22. 22
  23. 23     @Override
  24. 24     public void run() {
  25. 25         while (true) {
  26. 26
  27. 27             try {
  28. 28                 Gift gift = queue.take();
  29. 29                 log.warn(name + "购买了: {} ,剩余空间: {}", gift, queue.remainingCapacity());
  30. 30                 TimeUnit.MILLISECONDS.sleep(3000);
  31. 31             } catch (InterruptedException e) {
  32. 32                 log.error("Consumer  {} catch a ex", name, e);
  33. 33             }
  34. 34         }
  35. 35     }
  36. 36 }
复制代码
实行后效果如下:
注意由于是多线程在利用,所以某一秒处的日志大概是乱序的,
感兴趣的同学可以自行分析下
  1. 17:13:37.477 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂开始生产:Gift(name=lenovo, price=12888, completeTime=1724750022471)
  2. 17:13:37.478 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂开始生产:Gift(name=iphone, price=8888, completeTime=1724750022471)
  3. 17:13:37.478 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂开始生产:Gift(name=LV, price=28888, completeTime=1724750022473)
  4. 17:13:37.486 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂生产了:Gift(name=iphone, price=8888, completeTime=1724750022471), 剩余空间1
  5. 17:13:37.486 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小Z购买了: Gift(name=iphone, price=8888, completeTime=1724750022471) ,剩余空间: 2
  6. 17:13:37.486 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小L购买了: Gift(name=lenovo, price=12888, completeTime=1724750022471) ,剩余空间: 2
  7. 17:13:37.486 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂生产了:Gift(name=lenovo, price=12888, completeTime=1724750022471), 剩余空间2
  8. 17:13:37.486 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂生产了:Gift(name=LV, price=28888, completeTime=1724750022473), 剩余空间2
  9. 17:13:40.491 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小Z购买了: Gift(name=LV, price=28888, completeTime=1724750022473) ,剩余空间: 3
  10. 17:13:47.491 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂开始生产:Gift(name=LV, price=28888, completeTime=1724750032491)
  11. 17:13:47.491 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂开始生产:Gift(name=iphone, price=8888, completeTime=1724750032491)
  12. 17:13:47.491 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂开始生产:Gift(name=lenovo, price=12888, completeTime=1724750032491)
  13. 17:13:47.491 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂生产了:Gift(name=lenovo, price=12888, completeTime=1724750032491), 剩余空间1
  14. 17:13:47.491 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂生产了:Gift(name=LV, price=28888, completeTime=1724750032491), 剩余空间2
  15. 17:13:47.491 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小Z购买了: Gift(name=iphone, price=8888, completeTime=1724750032491) ,剩余空间: 2
  16. 17:13:47.491 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂生产了:Gift(name=iphone, price=8888, completeTime=1724750032491), 剩余空间2
  17. 17:13:47.491 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小L购买了: Gift(name=LV, price=28888, completeTime=1724750032491) ,剩余空间: 2
复制代码
接下来简单说下BlockingQueue的几种实现方式的内部逻辑和使用场景
1、ArrayBlockingQueue
内部使用数组实现缓冲区,(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )有界队列;
使用ReentrantLock锁来包管线程安全
可以满足大部分的业务场景。
2、LinkedBlockingQueue
内部使用了单链表实现了缓冲区,可以是无界队列,也可以是有界队列;
使用读写锁来包管线程安全。
适用于队列弹性比力大,并发性要求高的场景。
3、SynchronousQueue
同队伍列
很多人称如果想要任务快速实行,可以使用该队列。容易让别人有误解,不如我们来举个实际的例子
将主类中的blockingqueue 切换为SynchronousQueue,
  1. BlockingQueue<Gift> queue = new SynchronousQueue<>();
复制代码
输入为下,下面是前13秒是的输出,赤色字体为我的解释:
  1. 15:35:30.906 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂开始生产:Gift(name=LV, price=28888, completeTime=1724744135902)
  2. 15:35:30.915 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂生产了:Gift(name=LV, price=28888, completeTime=1724744135902), 剩余空间0
  3. 15:35:30.907 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂开始生产:Gift(name=lenovo, price=12888, completeTime=1724744135901)
  4. 15:35:30.915 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小L购买了: Gift(name=LV, price=28888, completeTime=1724744135902) ,剩余空间: 0
  5. 15:35:30.906 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂开始生产:Gift(name=iphone, price=8888, completeTime=1724744135901)
  6. 15:35:30.915 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂生产了:Gift(name=lenovo, price=12888, completeTime=1724744135901), 剩余空间0
  7. 15:35:30.915 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小Z购买了: Gift(name=lenovo, price=12888, completeTime=1724744135901) ,剩余空间: 0
  8. 请求之后,工厂分别生产了3个产品:手机、电脑、LV<br>之后LV 和电脑 都被消费了,此时iPhone还属于待消费状态<br>
  9. 15:35:33.916 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小L购买了: Gift(name=iphone, price=8888, completeTime=1724744135901) ,剩余空间: 0
  10. 15:35:33.916 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂生产了:Gift(name=iphone, price=8888, completeTime=1724744135901), 剩余空间0
  11. 消费者睡眠3秒钟以后,消费了手机<br>此时手机的生产者才开始打印日志,标明此时put方法的阻塞状态才结束<br>
复制代码
注意末了的时间点 15:35:33.916
消费者第二次消费完,iPhone的厂商立即打印了日志,所以之前iPhone的厂商在放置数据的过程中,一直处于一个阻塞的状态。
也就是如果消费者不取,那么生产者就一直处于出近况态。这恰恰是如果是快速消费的场景,可以使用此方案,而不是此方案可以让你的任务快速实行。当然我们通过名字其实也可以判断。
这种场景现实中有么?
也是有的,比如服务员找零,一样平常会将钱放在手里,等你拿了钱才会做接下来的动作。像这种需要同步交接,快速相应的场景,那么就可以思量SynchronousQueue。
当然实际场景中,服务员也不大概一直等着,消费者大概一直不拿钱(超时设定),消费者不收钱(通过InterruptedException 打断阻塞)。
4、PriorityBlockingQueue
优先级的阻塞队列,想法其实很简单,就是消费者不再是先进先出的获取数据,而是允许根据优先级排序后,优先拿优先级高的产品。队列内部是通过最小堆来维护队列的,我们在创建队列时,
要指定比力算法。如下,我们使用的是按照价格由高到低的方式获取产品,同时调解生产者速率>消费者速率(调解生产者sleep 为1000ms即可):
  1.         BlockingQueue<Gift> queue = new PriorityBlockingQueue<>(3, (o1, o2) -> o2.getPrice() - o1.getPrice());
复制代码
输出结果如下,我们可以看到消费者只获取当前队列中代价最高的产品:
  1. 18:39:01.040 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂开始生产:Gift(name=iphone, price=8888, completeTime=1724755146036)
  2. 18:39:01.040 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂开始生产:Gift(name=lenovo, price=12888, completeTime=1724755146036)
  3. 18:39:01.040 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂开始生产:Gift(name=LV, price=28888, completeTime=1724755146036)
  4. 18:39:01.045 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂生产了:Gift(name=LV, price=28888, completeTime=1724755146036),
  5. 18:39:01.045 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小Z购买了: Gift(name=LV, price=28888, completeTime=1724755146036) ,
  6. 18:39:01.045 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂生产了:Gift(name=lenovo, price=12888, completeTime=1724755146036),
  7. 18:39:01.045 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小L购买了: Gift(name=lenovo, price=12888, completeTime=1724755146036) ,
  8. 18:39:01.045 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂生产了:Gift(name=iphone, price=8888, completeTime=1724755146036),
  9. 18:39:02.059 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂开始生产:Gift(name=LV, price=28888, completeTime=1724755147059)
  10. ...省略一部分日志....
  11. 18:39:03.069 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂生产了:Gift(name=LV, price=28888, completeTime=1724755148069),
  12. 18:39:03.069 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂生产了:Gift(name=lenovo, price=12888, completeTime=1724755148069),
  13. 18:39:04.052 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小Z购买了: Gift(name=LV, price=28888, completeTime=1724755148069) ,
  14. 18:39:04.052 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小L购买了: Gift(name=LV, price=28888, completeTime=1724755147059) ,
复制代码
5、DelayQueue
这个队列也很有意思,它需要有产品实现一个delay接口,接口实时的返回还要多久这个产品可用。
如下我们切换为 DelayQueue。
效果如下:
消费者即使已经触发获取,(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )但是还是无法立即拿到,需要在delay()返回非正数以后才华获取。如许生产者可以生产一些内部偶然间概念的产品,起到一个定时器的作用。
举个例子:
我们装修了一间房子,由于装修有害物质,我们需要6个月后才华入住,
常用的办法如下:
1、添加定时器,由定时器来触发,但是显然要有外部依赖其他对象。
2、反复获取,拿到之后check时间,如果未到时间,重新丢回队列,但是如许显然过于复杂,系统的调用频次也会上去。
3、消费者来获取产品时,判断时间是否可取,如果不可取就一直等待到可取到产品为止。注意此时消费线程会阻塞到该队列头部的产品,并不会越过它实验拿后续的产品。(DelayQueue选用此种策略)
我们先修改缓冲队列为DelayQueue
  1. BlockingQueue<Gift> queue = new DelayQueue<>();
复制代码
生产者的时间周期改为2s,消费者的时间周期改为4s ,假设产品的过期时间是5s注意这几个时间节点,
Gift 类的代码我们需要改造一下,方便定位分析:
  1. 1 package com.example.demo.learnblockingqueue;
  2. 2
  3. 3 import lombok.Data;
  4. 4 import lombok.NoArgsConstructor;
  5. 5 import lombok.extern.slf4j.Slf4j;
  6. 6
  7. 7 import java.util.Date;
  8. 8 import java.util.concurrent.Delayed;
  9. 9 import java.util.concurrent.TimeUnit;
  10. 10
  11. 11 /**
  12. 12  * @discription
  13. 13  */
  14. 14 @Data
  15. 15 @NoArgsConstructor
  16. 16 @Slf4j
  17. 17 public class Gift implements Delayed {
  18. 18
  19. 19     private String name;
  20. 20
  21. 21     private int price;
  22. 22
  23. 23     private final long completeTime = new Date().getTime() + 5000;
  24. 24
  25. 25     public Gift(Gift giftSample) {
  26. 26         name = giftSample.getName() + "_" + completeTime;
  27. 27         price = giftSample.getPrice();
  28. 28     }
  29. 29
  30. 30     public Gift(String name, int price) {
  31. 31         this.name = name;
  32. 32         this.price = price;
  33. 33     }
  34. 34
  35. 35     private void printLog() {
  36. 36         log.warn(Thread.currentThread() + "     !!!!"+ "_" + name);
  37. 37     }
  38. 38
  39. 39     @Override
  40. 40     public long getDelay(TimeUnit unit) {
  41. 41         printLog();
  42. 42         return unit.convert(completeTime - new Date().getTime(), TimeUnit.MILLISECONDS);
  43. 43     }
  44. 44
  45. 45     @Override
  46. 46     public int compareTo(Delayed o) {
  47. 47         return 0;
  48. 48     }
  49. 49 }
复制代码
效果大概是如许的:
是不是和我们假想的不太一样,直接说发生了什么,注意看不同颜色的分析对应的不同的颜色的日志:
起首是线程5 消费者抢到了锁,则直接等待到产品到期,注意线程5不是按照我们约定的周期查抄的,然后二次确认时间,接着就消费了(24秒--->29秒)
此时线程4抢到了下一把锁,注意下一个礼物是最新生产的产品,而不是最早生产的产品,然后等待产品到期时间,二次确认并消费(28秒--->33秒)注意在二次确认的时间的时候,两个线程都有确认,但是只有一个线程真正会消费成功,这不影响使用效果(推测这里是为了提高性能,并没有完全,没有采取很重的锁)。
接下来的逻辑一样
  1. Connected to the target VM, address: '127.0.0.1:54328', transport: 'socket'
  2. 19:52:24.292 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂开始生产:Gift(name=LV_1724759549288, price=28888, completeTime=1724759549288)
  3. 19:52:24.292 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂开始生产:Gift(name=lenovo_1724759549289, price=12888, completeTime=1724759549289)
  4. 19:52:24.292 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂开始生产:Gift(name=<strong>iphone_1724759549288</strong>, price=8888, completeTime=1724759549288)
  5. 19:52:24.300 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Gift - Thread[pool-1-thread-5,5,main]     !!!!<strong>_LV_1724759549288
  6. </strong>19:52:24.300 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂生产了:Gift(name=LV_1724759549288, price=28888, completeTime=1724759549288),
  7. 19:52:24.300 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂生产了:Gift(name=lenovo_1724759549289, price=12888, completeTime=1724759549289),
  8. 19:52:24.302 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂生产了:Gift(name=iphone_1724759549288, price=8888, completeTime=1724759549288),
  9. ..省略..
  10. 19:52:28.321 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂生产了:Gift(name=LV_1724759553321, price=28888, completeTime=1724759553321),
  11. 19:52:28.321 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂生产了:Gift(name=lenovo_1724759553321, price=12888, completeTime=1724759553321),
  12. 19:52:28.321 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂生产了:Gift(name=<strong>iphone_1724759553321</strong>, price=8888, completeTime=1724759553321),
  13. 19:52:29.300 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Gift - Thread[pool-1-thread-5,5,main]     !!!!<strong>_LV_1724759549288
  14. </strong>19:52:29.300 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Gift - Thread[pool-1-thread-4,5,main]     !!!!<strong>_iphone_1724759553321
  15. </strong>19:52:29.300 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小L购买了: Gift(name=<strong>LV_1724759549288</strong>, price=28888, completeTime=1724759549288) ,
  16. 19:52:30.326 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂开始生产:Gift(name=LV_1724759555326, price=28888, completeTime=1724759555326)
  17. 19:52:30.326 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂开始生产:Gift(name=iphone_1724759555326, price=8888, completeTime=1724759555326)
  18. ...省略..
  19. 19:52:32.334 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂开始生产:Gift(name=iphone_1724759557334, price=8888, completeTime=1724759557334)
  20. 19:52:32.334 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂生产了:Gift(name=LV_1724759557334, price=28888, completeTime=1724759557334),
  21. 19:52:32.334 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂生产了:Gift(name=<strong>iphone_1724759557334</strong>, price=8888, completeTime=1724759557334),
  22. 19:52:32.334 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂生产了:Gift(name=lenovo_1724759557334, price=12888, completeTime=1724759557334),
  23. 19:52:33.301 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Gift - Thread[pool-1-thread-5,5,main]     !!!!<strong>_iphone_1724759553321
  24. </strong>19:52:33.331 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Gift - Thread[pool-1-thread-4,5,main]     !!!!<strong>_iphone_1724759553321
  25. </strong>19:52:33.331 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Gift - Thread[pool-1-thread-5,5,main]     !!!!<strong>_iphone_1724759557334
  26. </strong>19:52:33.331 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小Z购买了: Gift(name=<strong>iphone_1724759553321</strong>, price=8888, completeTime=1724759553321) ,
  27. 19:52:34.346 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂开始生产:Gift(name=lenovo_1724759559346, price=12888, completeTime=1724759559346)
  28. 19:52:34.346 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂开始生产:Gift(name=LV_1724759559346, price=28888, completeTime=1724759559346)
  29. 19:52:34.346 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂开始生产:Gift(name=iphone_1724759559346, price=8888, completeTime=1724759559346)
  30. ...省略..
  31. 19:52:36.361 [pool-1-thread-3] WARN com.example.demo.learnblockingqueue.Producer - AAAA  LV代工厂生产了:Gift(name=LV_1724759561361, price=28888, completeTime=1724759561361),
  32. 19:52:36.361 [pool-1-thread-2] WARN com.example.demo.learnblockingqueue.Producer - AAAA  联想代工厂生产了:Gift(name=lenovo_1724759561361, price=12888, completeTime=1724759561361),
  33. 19:52:36.361 [pool-1-thread-1] WARN com.example.demo.learnblockingqueue.Producer - AAAA  苹果代工厂生产了:Gift(name=iphone_1724759561361, price=8888, completeTime=1724759561361),
  34. Disconnected from the target VM, address: '127.0.0.1:54328', transport: 'socket'(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )
  35. 19:52:37.339 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Gift - Thread[pool-1-thread-5,5,main]     !!!!<strong>_iphone_1724759557334
  36. </strong>19:52:37.340 [pool-1-thread-4] WARN com.example.demo.learnblockingqueue.Gift - Thread[pool-1-thread-4,5,main]     !!!!_iphone_1724759561361
  37. 19:52:37.339 [pool-1-thread-5] WARN com.example.demo.learnblockingqueue.Consumer - BBBB  小L购买了: Gift(name=<strong>iphone_1724759557334</strong>, price=8888, c
复制代码
以上我们可以得到两个重要结论:
DelayQueue并不是按照顺序进行消费的,而是获取最新的的数据进行实验获取,(只管此时队列中已经存在可用的产品)
DelayQueue唤醒消费者的时间,是按照产品的到达可用状态的时间后,才会唤醒
因此使用DelayQueue时,我们要注意,生产商品不能太激烈,生产速率不要大于消费速率,否则产品很大概消费不到了(当然也可以利用这个规则,将旧的产品进行淘汰处理)
产品的delay时间不能太长,否则大概会导致消费者一直处于挂起状态。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我爱普洱茶

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表