多线程+阻塞队列实现生产者-消费者模型获取队列数据问题
来源:互联网 发布:xpath获取端口号 编辑:程序博客网 时间:2024/06/09 22:44
最近在研究服务端推送技术,使用后台轮询的方式hold住连接,当有符合条件的数据产生时推送数据到前台。业务定期产生数据放到队列中,连接循环从队列中取数据,由于存在多个连接从同一队列中取数据的情况,考虑到是否会有数据不能被及时消费,或者队首数据一直不能被消费造成死循环的情况。
在网上查了一下多线程时间片段分配,如果没有设定优先级,各线程应该是有均等的机会被执行的。本着严谨的态度,通过程序做了如下测试。
生产线程
public class QueueDataGenerator implements Runnable{ public static BlockingQueue<String> queue = new LinkedBlockingQueue<String>(); public static boolean run = false; @Override public void run() { run = true; Random r = new Random(); SimpleDateFormat format = new SimpleDateFormat("mm:ss"); for (int i = 0; i < 100; i++) { String v = String.valueOf(r.nextInt(10)); try { String ms = format.format(new Date()); System.out.println("put data '"+ v +"' to queue. CurrentTime:"+ ms); queue.put(v); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } run = false; }}
循环向队列中放入数据,每次放入一个0-9的随机整数
消费线程
public class Polling implements Runnable{ private String id; /** * . * @param id */ public Polling(String id) { this.id = id; } @Override public void run() { SimpleDateFormat format = new SimpleDateFormat("mm:ss"); while(QueueDataGenerator.run){ String v = QueueDataGenerator.queue.peek(); if (id.equals(v)) { String ms = format.format(new Date()); System.out.println("Polling with id '"+ id +"' match. CurrentTime:"+ ms); QueueDataGenerator.queue.remove(v); } //try { //Thread.sleep(1000); //} catch (InterruptedException e) { //e.printStackTrace(); //} } }}
通过QueueDataGenerator.run判断是否处在队列数据生产周期,若是则循环从队列中取数据,peek()方法不会移除队首数据,每个消费者有自己的标识id,若队首数据与id相等,则移除数据,表明数据被成功消费。
下面是测试类
public class Test { public static void main(String[] args) { QueueDataGenerator dataGenerator = new QueueDataGenerator(); Thread t1 = new Thread(dataGenerator); t1.start(); for (int i = 0; i < 10; i++) { String id = String.valueOf(i); Polling polling = new Polling(id); Thread t = new Thread(polling); t.start(); } }}
开启生产线程,然后循环开启10个消费线程。
为方便观察数据变化,打印了时间(分/秒),部分测试结果如下:
put data '5' to queue. CurrentTime:14:33Polling with id '5' match. CurrentTime:14:33put data '6' to queue. CurrentTime:14:35Polling with id '6' match. CurrentTime:14:35put data '8' to queue. CurrentTime:14:37Polling with id '8' match. CurrentTime:14:37put data '1' to queue. CurrentTime:14:39Polling with id '1' match. CurrentTime:14:39put data '9' to queue. CurrentTime:14:41Polling with id '9' match. CurrentTime:14:41put data '7' to queue. CurrentTime:14:43Polling with id '7' match. CurrentTime:14:43
因为生产线程是2秒产生一个数据,可以看到每个数据都能被对应的线程消费,不存在线程“争抢”影响其他消费线程执行的情况。
进一步测试消费线程执行时间过长是否会对结果产生影响,打开注释代码,
让消费线程sleep一秒:
put data '9' to queue. CurrentTime:19:27Polling with id '9' match. CurrentTime:19:28put data '1' to queue. CurrentTime:19:29Polling with id '1' match. CurrentTime:19:30put data '5' to queue. CurrentTime:19:31Polling with id '5' match. CurrentTime:19:31put data '4' to queue. CurrentTime:19:33Polling with id '4' match. CurrentTime:19:33put data '8' to queue. CurrentTime:19:35Polling with id '8' match. CurrentTime:19:35
sleep 3秒:
put data '2' to queue. CurrentTime:25:24put data '9' to queue. CurrentTime:25:26Polling with id '2' match. CurrentTime:25:27put data '7' to queue. CurrentTime:25:28Polling with id '9' match. CurrentTime:25:30put data '6' to queue. CurrentTime:25:30put data '3' to queue. CurrentTime:25:32Polling with id '7' match. CurrentTime:25:33Polling with id '6' match. CurrentTime:25:33put data '9' to queue. CurrentTime:25:34Polling with id '3' match. CurrentTime:25:36put data '8' to queue. CurrentTime:25:36put data '9' to queue. CurrentTime:25:38Polling with id '9' match. CurrentTime:25:39
可以看出,执行时间长也只是被消费的时间延长相应时间(随着执行时间间隔可能越来越长),并不会造成某些数据不能被消费。一般基于实时性考虑,不会使消费线程执行时间过长,可以将复杂业务逻辑放到生产线程中,消费线程直接拿到可以展示的结果数据。
阅读全文
1 0
- 多线程+阻塞队列实现生产者-消费者模型获取队列数据问题
- 通过阻塞队列实现生产者消费者模型
- 阻塞队列实现生产者消费者
- wait,notify,非阻塞队列实现生产者,消费者模型
- 队列实现生产者消费者模型
- 并发:阻塞队列与生产者消费者模型
- 阻塞队列 生产者消费者
- 阻塞队列实现生产者消费者模式
- 阻塞队列---实现生产者消费者模式
- 阻塞队列实现生产者消费者模式
- 阻塞队列实现生产者消费者模式
- 阻塞队列实现生产者消费者模式
- 阻塞队列实现生产者消费者模式
- 生产者-消费者模式(阻塞队列实现)
- 使用阻塞队列BlockingQueue实现生产者消费者
- 阻塞队列实现生产者消费者模式
- 基于阻塞队列实现消费者和生产者
- 基于阻塞队列实现消费者和生产者
- 后代选择器+nth-child()选择器
- VMware虚拟机NAT模式连不上网,无法启动VMware DHCP Service 服务
- 74 hc573编程
- Delphi ISO collection
- 面向对象-数组工具
- 多线程+阻塞队列实现生产者-消费者模型获取队列数据问题
- 插入排序和选择排序
- web
- HTML学习笔记6 表单标签
- PHP单一入口概述与优缺点分析
- git小技巧--如何从其他分支merge个别文件或文件夹
- LeetCode46_Permutations
- jstree 请求后台数据前台处理
- Angular在IE浏览器下的配置