C# 生产者与消费者模式
情景:一个线程不断获取数据,另一个线程不断处理这些数据。
常规方法:数据列表加锁,两个线程获取锁,拿到操作权;类似代码如下:(不推荐)
static void Main(string[] args)
{
lockClass l = new lockClass();
for (int i = 0; i < 1000000; i++)
{
l.Equeue(i.ToString()); }
} public class lockClass
{
Queue<string> currentQueue = new Queue<string>(10000000);//当前要插入数据的队列
static readonly object objlock = new object();
FileStream f = new FileStream("D://1.txt", FileMode.Create, FileAccess.Write, FileShare.None);
StreamWriter writer;
public lockClass()
{
writer = new StreamWriter(f);
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerAsync();
}
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
lock (objlock)
{
if (currentQueue.Count > 0)
{
var item = currentQueue.Dequeue();
Console.WriteLine(item);
writer.WriteLine(item); } } }
} public void Equeue(string item)
{
lock (objlock)
{ currentQueue.Enqueue(item); }
} }
方法2:双缓存队列处理,意思就是说,用两个队列,一个队列用于获取数据,另一个队列用于操作数据,通过信号量来处理线程调度,来取消“锁”带来的资源切换浪费,参考代码如下:
static void Main(string[] args)
{
var test = new DoubleBufferedQueue();
for (int i = 0; i < 1000000; i++)
{
test.Equeue(i.ToString()); }
} public class DoubleBufferedQueue
{
public readonly Queue<string> Queue1 = new Queue<string>(10000000);
public readonly Queue<string> Queue2 = new Queue<string>(10000000);
private readonly ManualResetEvent lock1 = new ManualResetEvent(true);//一开始可以执行
private readonly ManualResetEvent lock2 = new ManualResetEvent(false);
private readonly AutoResetEvent _autoReset = new AutoResetEvent(true);
private volatile Queue<string> currentQueue = new Queue<string>(10000000);//当前要插入数据的队列
FileStream f = new FileStream("D://1.txt", FileMode.Create, FileAccess.Write, FileShare.None);
StreamWriter writer;
public DoubleBufferedQueue()
{
writer = new StreamWriter(f);
currentQueue = Queue1;
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerAsync();
} void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
this._autoReset.WaitOne();//没有成员入队列时不进行其他操作;
this.lock2.Reset();
this.lock1.WaitOne();
var readQueue = currentQueue;
currentQueue = (currentQueue == Queue1) ? Queue2 : Queue1;
this.lock2.Set();
writeToConsonle(currentQueue); }
} void writeToConsonle(Queue<string> readQueue)
{ while (readQueue.Count > 0)
{
var item= readQueue.Dequeue();
Console.WriteLine(item);
writer.WriteLine(item);
}
} public void Equeue(string item)
{
this.lock2.WaitOne();
this.lock1.Reset();
currentQueue.Enqueue(item);
lock1.Set();
_autoReset.Set();
} }
方法3:用微软提供的BlockingCollection(线程安全的,可阻塞的资源的),个人理解就是资源安全的队列,并且当没有操作的时候(队列空闲的时候)不耗费资源,个人觉得和方法2原理类似(推荐使用)
static void Main(string[] args)
{ var block = new blockingCollectionClass();
for (int i = 0; i < 10000; i++)
{ block.Add(i.ToString()); }
Console.ReadKey();
} public class blockingCollectionClass
{
BlockingCollection<string> blockingCollection = new BlockingCollection<string>();
FileStream f = new FileStream("D://1.txt", FileMode.Create, FileAccess.Write, FileShare.None);
StreamWriter writer;
public void Add(string Item)
{
blockingCollection.Add(Item);
} public blockingCollectionClass()
{
writer = new StreamWriter(f);
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerAsync();
} void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (string value in blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine(value);
writer.WriteLine(value);
}
} }
情景2:秒杀活动、抢票等活动时,并发性很高,导致服务器阻塞,用户请求丢失;
策略1:可以采用以上队列的形式处理服务器高并发问题,所有的请求先加入队列,排队,后台线程来处理队列里面的请求;
策略2:够建一个队列容器,接收请求的线程从容器中取一个空的对列,当队列填满后,放回到容器中,再次从容器中取一个空队列;处理线程需要从容器中取出非空的队列,处理完队列为空,放回到容器去;从容器中取放队列需要加锁。如果要保证处理的顺序,容器可以选队列(放队列的队列);
C# 生产者与消费者模式的更多相关文章
- 使用libuv实现生产者和消费者模式
生产者和消费者模式(Consumer + Producer model) 用于把耗时操作(生产线程),分配给一个或者多个额外线程执行(消费线程),从而提高生产线程的响应速度(并发能力) 定义 type ...
- java生产者与消费者模式
前言: 生产者和消费者模式是我们在学习多线程中很经典的一个模式,它主要分为生产者和消费者,分别是两个线程, 目录 一:生产者和消费者模式简介 二:生产者和消费者模式的实现 声明:本例来源于java经典 ...
- condition版生产者与消费者模式
1.简介 在爬虫中,生产者与消费者模式是经常用到的.我能想到的比较好的办法是使用redis或者mongodb数据库构造生产者消费者模型.如果直接起线程进行构造生产者消费者模型,线程容易假死,也难以构造 ...
- Java并发编程(4)--生产者与消费者模式介绍
一.前言 这种模式在生活是最常见的,那么它的场景是什么样的呢? 下面是我假象的,假设有一个仓库,仓库有一个生产者和一个消费者,消费者过来消费的时候会检测仓库中是否有库存,如果没有了则等待生产,如果有就 ...
- Java多线程设计模式(2)生产者与消费者模式
1 Producer-Consumer Pattern Producer-Consumer Pattern主要就是在生产者与消费者之间建立一个“桥梁参与者”,用来解决生产者线程与消费者线程之间速度的不 ...
- 【爬虫】Condition版的生产者和消费者模式
Condition版的生产者和消费者模式 threading.Condition 在没有数据的时候处于阻塞状态,有数据可以使用notify的函数通知等等待状态的线程运作 threading.Condi ...
- 【爬虫】Load版的生产者和消费者模式
''' Lock版的生产者和消费者模式 ''' import threading import random import time gMoney = 1000 # 原始金额 gLoad = thre ...
- java 线程并发(生产者、消费者模式)
线程并发协作(生产者/消费者模式) 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”. Ø 什么是生产者? 生产者指的是负责生产数 ...
- java进阶(40)--wait与notify(生产者与消费者模式)
文档目录: 一.概念 二.wait的作用 三.notify的作用 四.生产者消费者模式 五.举例 ---------------------------------------分割线:正文------ ...
- Java实现生产者与消费者模式
生产者不断向队列中添加数据,消费者不断从队列中获取数据.如果队列满了,则生产者不能添加数据:如果队列为空,则消费者不能获取数据.借助实现了BlockingQueue接口的LinkedBlockingQ ...
随机推荐
- 【未解决】iOS QBImagePickerController访问相册没有取消和确定按钮
这两天调程序时遇到了这个问题,如图所示: 感觉这问题也是奇葩………… 用系统的 UIImagePickerController 替换后就正常了.看来是 QBImagePickerController ...
- webupload项目中使用
目前项目需要一个多图上传的功能,使用LayUI并也是可以实现多图上传的,但是没有图片删除功能,参考了一下网上多图上传的插件,选择了WebUpload进行功能开发. 然而不幸的是,官方的插件并不带UI界 ...
- JAVA基础知识(六)Java 静态多分派&动态单分派
1.分派发生在编译期和运行期,编译期的分派为静态分派,运行期的为动态分派. 2.编译期是根据对象声明的类型来选择方法,运行期是根据对象实际类型来选择方法. 3.单分派和多分派取决于宗量, 方法调用者和 ...
- 微服务与网关技术(SIA-GateWay)
一.背景 软件架构,总是在不断的演进中... 把时间退回到二十年之前,当时企业级领域研发主要推崇的还是C/S模式,PB.Delphi这样的开发软件是企业应用开发的主流.随着时间的推移,基于浏览器的B/ ...
- 动态SQL查询
if+where: 用于查询操作,where标签可以智能判断是否添加and.or.where关键词 示例: <select id="findByParam" resultTy ...
- 使用DOM4J 对xml解析操作
参考自:https://blog.csdn.net/redarmy_chen/article/details/12969219 dom4j是一个Java的XML API,类似于jdom,用来读写XML ...
- 记一次解决tomcat自动关闭的bug
最近一个运行了4年的javaee web项目,经常接到客户反馈系统无法打开.登录服务器查看服务,发现是tomcat自动关闭了.基本是3到4天发生一次. 运维人员开始以为是其他服务杀死了tomcat服务 ...
- 数据库炸了——是谁动了我的wait_timeout
1.起因 隐约听到坐在我对面的测试说测试环境的接口有问题 他们一番商讨后,朝我这边反馈说,现在测试环境的接口报504 我条件反射的回了句那是接口超时,再多试几次(测试环境的性能比较差,尤其是数据库,经 ...
- CGI getenv 参数
变量名 描述 CONTENT_TYPE 这个环境变量的值指示所传递来的信息的MIME类型.目前,环境变量CONTENT_TYPE一般都是:application/x-www-form-urlencod ...
- Linux配置部署_新手向(二)——Nginx安装与配置
目录 前言 Nginx 配置(后续补充) 小结 @ 前言 上一篇整完Linux系统的安装,紧接着就开始来安装些常用的东西吧,首先Nginx. Nginx 简介 Nginx作为转发,负载均衡,凭着其高性 ...