你真的知道.NET Framework中的阻塞队列BlockingCollection的妙用吗?
BlockingCollection集合是一个拥有阻塞功能的集合,它就是完成了经典生产者消费者的算法功能。一般情况下,我们可以基于 生产者 - 消费者模式来实现并发。BlockingCollection<T> 类是最好的解决方案
刚结束的物联网卡项目,我需要调用移动的某个具有批量获取物联网卡数据的接口,其实最主要的数据就是物联网卡卡号,然后通过这两个卡号去调用其余的两个接口,最后拼接起来,就有了物联网卡的完整信息。但是问题来了,物联网卡数量多,而且每次调用接口还需要费上一到两秒,如果正常的读取,那不得慢死,所以就用并发来做。我想到的是阻塞队列+生产者消费者模型,使用的阻塞队列是.net线程安全集合的BlockingCollection, 具体的可以看《你不能错过.net 并发解决方案》《深入理解阻塞队列》《.net framework 4 线程安全概述》。
但是问题来了,MSDN上的例子以及《C# 高级编程第九版》中的管道模型代码都是基于单个的Task, 在这里我肯定是用了多个Task去读取接口,为什么我要说这点,多线程是不可测得,我如何识别阻塞队列已满,如何及时获取阻塞队列中的数据,并不重复的获取呢?具体的简单demo,请看《你不能错过.net 并发解决方案》。我一开始是这么写的:
BlockingCollection<string> blockingCollection = new BlockingCollection<string>();
ConcurrentQueue<string> concurrentQueue = new ConcurrentQueue<string>(); var t = new Task[];
for (int i = ; i <= ; i++)
{
t[i] = Task.Factory.StartNew((obj) =>
{
Thread.Sleep();
blockingCollection.Add(obj.ToString());
concurrentQueue.Enqueue(obj.ToString());
Console.WriteLine("Task中的数据: {0}", obj.ToString());
}, i + );
} Thread.Sleep();
while (!blockingCollection.IsCompleted)
{
foreach (var b in blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine("开始输出阻塞队列: {0}", b);
Console.WriteLine(blockingCollection.IsCompleted);
Console.WriteLine("并发队列的数量: {0}", concurrentQueue.Count);
} Console.WriteLine("调用GetConsumingEnumerable方法遍历完之后阻塞队列的数量: {0}", blockingCollection.Count); if (concurrentQueue.Count == )
{
blockingCollection.CompleteAdding();
}
} Console.WriteLine("********"); Console.WriteLine("是否完成添加: {0}", blockingCollection.IsAddingCompleted); Console.Read();
但是结果:
可以看到,这结果有问题啊,按道理来讲foreach遍历完了就会出来啊,但是这是阻塞队列,肯定不是这样的,那么什么时候能挑出foreach循环?这就和BlockingCollection的设计有关了,我查看了下它的源码,原谅我没有看懂,也就不贴了。后来,我改了下代码,就解决问题了。
///// 后续补充
BlockingCollection的GetComsumingEnumerate方法跳出循环的标志是BlockingCollection的IsCompleteAdding为true并且BlockingCollection集合的数据为空
/////
BlockingCollection<string> blockingCollection = new BlockingCollection<string>();
ConcurrentQueue<string> concurrentQueue = new ConcurrentQueue<string>(); var t = new Task[];
for (int i = ; i <= ; i++)
{
t[i] = Task.Factory.StartNew((obj) =>
{
Thread.Sleep();
blockingCollection.Add(obj.ToString());
concurrentQueue.Enqueue(obj.ToString());
Console.WriteLine("Task中的数据: {0}", obj.ToString());
}, i+);
} Thread.Sleep();
while (!blockingCollection.IsCompleted)
{
foreach (var b in blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine("开始输出阻塞队列: {0}", b);
Console.WriteLine(blockingCollection.IsCompleted);
Console.WriteLine("并发队列的数量: {0}", concurrentQueue.Count);
if (concurrentQueue.Count == 50)
{
blockingCollection.CompleteAdding();
}
}
Console.WriteLine("调用GetConsumingEnumerable方法遍历完之后阻塞队列的数量: {0}", blockingCollection.Count); } Console.WriteLine("********"); Console.WriteLine("是否完成添加: {0}", blockingCollection.IsAddingCompleted);
结果:
我没有写的很详细,因为,只是做个笔记,平时学习的时候没有注意到这些问题,没有遇到特定情况下的问题,项目开发中遇到了,就记录下。
你真的知道.NET Framework中的阻塞队列BlockingCollection的妙用吗?的更多相关文章
- 聊聊并发(七)——Java中的阻塞队列
3. 阻塞队列的实现原理 聊聊并发(七)--Java中的阻塞队列 作者 方腾飞 发布于 2013年12月18日 | ArchSummit全球架构师峰会(北京站)2016年12月02-03日举办,了解更 ...
- Java中的阻塞队列(BlockingQueue)
1. 什么是阻塞队列 阻塞队列(BlockingQueue)是 Java 5 并发新特性中的内容,阻塞队列的接口是 java.util.concurrent.BlockingQueue,它提供了两个附 ...
- Java中的阻塞队列-ArrayBlockingQueue(一)
最近在看一些java基础的东西,看到了队列这章,打算对复习的一些知识点做一个笔记,也算是对自己思路的一个整理,本章先聊聊java中的阻塞队列 参考文章: http://ifeve.com/java-b ...
- 多线程编程学习六(Java 中的阻塞队列).
介绍 阻塞队列(BlockingQueue)是指当队列满时,队列会阻塞插入元素的线程,直到队列不满:当队列空时,队列会阻塞获得元素的线程,直到队列变非空.阻塞队列就是生产者用来存放元素.消费者用来获取 ...
- 阻塞队列一——java中的阻塞队列
目录 阻塞队列简介:介绍阻塞队列的特性与应用场景 java中的阻塞队列:介绍java中实现的供开发者使用的阻塞队列 BlockQueue中方法:介绍阻塞队列的API接口 阻塞队列的实现原理:具体的例子 ...
- JUC之Java中的阻塞队列及其实现原理
在文章线程池实现原理 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中介绍了线程池的组成部分,其中一个组成部分就是阻塞队列.那么JAVA中的阻塞队列如何实现的呢? 阻塞队列,关键字是阻塞 ...
- Java中的阻塞队列
1. 什么是阻塞队列? 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列.这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用 ...
- Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍
1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...
- 获取synchronized锁中的阻塞队列中的线程是非公平的
synchronized中阻塞队列的线程是非公平的 测试demo: import java.text.MessageFormat; import java.text.SimpleDateFormat; ...
随机推荐
- 对LCS算法及其变种的初步研究
LCS的全称为Longest Common Subsequence,用于查找两个字符串中的最大公共子序列,这里需要注意区分子序列与子串,所谓子序列,指的是从前到后,可以跳跃元素筛选,而字串则必须连续筛 ...
- 编译GDAL使用最新的HDF库配置文件
HDF库最新版本中的动态库以及目录结构都发生了变化,导致按照之前的博客进行编译GDAL时,会出问题.使用HDF4版本为HDF4-4.2.10,HDF5的版本为HDF5-1.8.12.两个库的目录结构如 ...
- 【Unity Shaders】Shader学习资源和Surface Shader概述
写在前面 写这篇文章的时候,我断断续续学习Unity Shader半年了,其实还是个门外汉.我也能体会很多童鞋那种想要学好Shader却无从下手的感觉.在这个期间,我找到一些学习Shader的教程以及 ...
- LCD 显示异常定位分析方法
第一种情况: 进入kernel或android 后,如果LCM图像示异常,可以通过如下步骤来判断问题出现在哪个层面. step1:通过DMMS截图,来判断上面刷到LCM的数据是否有问题. 若DMMS获 ...
- WebLogic11g-集群相关概念
weblogic集群架构相关的概念有: 1.服务器(server,控制台选择环境-服务器) 2.集群(cluster,控制台选择环境-集群) 3.计算机(machine,控制台选择环境-计算机) ...
- ADFS部署过程中设置network service对证书的读取权限
今儿在部署客户正式环境的ADFS时候遇到一问题,在配置完基于声明的身份验证后通过url访问居然报错了,这干过N回的事怎么会出错了呢,百思不得其解 网页报错如下 系统日志报错如下, 回想过程中的每一步, ...
- 在go中使用linked channels进行数据广播
在go中使用linked channels进行数据广播 原文在这里(需FQ),为啥想要翻译这篇文章是因为在实际中也碰到过如此的问题,而该文章的解决方式很巧妙,希望对大家有用. 在go中channels ...
- 【一天一道LeetCode】#86. Partition List
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...
- Chapter 2 User Authentication, Authorization, and Security(3):保护服务器避免暴力攻击
原文出处:http://blog.csdn.net/dba_huangzj/article/details/38756693,专题目录:http://blog.csdn.net/dba_huangzj ...
- 海量数据挖掘MMDS week3:流算法Stream Algorithms
http://blog.csdn.net/pipisorry/article/details/49183379 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...