Parallel Programming-多消费者,多生产者同时运行并行
在上一篇文章演示了并行的流水线操作(生产者和消费者并行同时执行),C#是通过BlockingCollection这个线程安全的对象作为Buffer,并且结合Task来实现的。但是上一篇文章有个缺陷,在整个流水线上,生产者和消费者是唯一的。本文将演示多个消费者多个生产者同时并行执行。
一、多消费者、多生产者示意图

与前一篇文章演示的流水线思想类似,不同之处就是本文的topic:消费者和生产者有多个,以buffer1为例,起生产者有两个,消费者有两个,现在有三个纬度的并行:
- Action1和Action2并行(消费者和生产者并行)
- 消费者并行(Action2.1和Action2.2并行)
- 生产者并行(Action1.1和Action1.2并行)
二、实现
2.1 代码
class PiplelineDemo
{
private int seed;
public PiplelineDemo()
{
seed = ;
} public void Action11(BlockingCollection<string> output)
{
for (var i = ; i < seed; i++)
{
output.Add(i.ToString());//initialize data to buffer1
}
} public void Action12(BlockingCollection<string> output)
{
for (var i = ; i < seed; i++)
{
output.Add(i.ToString());//initialize data to buffer1
}
} public void Action21(BlockingCollection<string> input, BlockingCollection<string> output)
{
foreach (var item in input.GetConsumingEnumerable())
{
var itemToInt = int.Parse(item);
output.Add((itemToInt * itemToInt).ToString());// add new data to buffer2
}
} public void Action22(BlockingCollection<string> input, BlockingCollection<string> output)
{
foreach (var item in input.GetConsumingEnumerable())
{
var itemToInt = int.Parse(item);
output.Add((itemToInt * itemToInt).ToString());// add new data to buffer2
}
} public void Action31(BlockingCollection<string> input, BlockingCollection<string> output)
{
foreach (var item in input.GetConsumingEnumerable())
{
output.Add((item));// add new data to buffer3
}
} public void Action32(BlockingCollection<string> input, BlockingCollection<string> output)
{
foreach (var item in input.GetConsumingEnumerable())
{
output.Add((item));// add new data to buffer3
}
}
public void Pipeline()
{
var buffer1 = new BlockingCollection<string>(seed * );
var buffer2 = new BlockingCollection<string>(seed * );
var buffer3 = new BlockingCollection<string>(seed * );
var taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None);
var stage11 = taskFactory.StartNew(() => Action11(buffer1));
var stage12 = taskFactory.StartNew(() => Action12(buffer1));
Task.Factory.ContinueWhenAll(new Task[] { stage11, stage12 }, (tasks) =>
{
buffer1.CompleteAdding();
});
var stage21 = taskFactory.StartNew(() => Action21(buffer1, buffer2));
var stage22 = taskFactory.StartNew(() => Action22(buffer1, buffer2));
Task.Factory.ContinueWhenAll(new Task[] { stage21, stage22 }, (tasks) =>
{
buffer2.CompleteAdding();
});
var stage31 = taskFactory.StartNew(() => Action31(buffer2, buffer3));
var stage32 = taskFactory.StartNew(() => Action32(buffer2, buffer3));
Task.Factory.ContinueWhenAll(new Task[] { stage31, stage32 }, (tasks) =>
{
buffer3.CompleteAdding();
});
Task.WaitAll(stage11, stage12, stage21, stage22, stage31, stage32);
foreach (var item in buffer3.GetConsumingEnumerable())//print data in buffer3
{
Console.WriteLine(item);
}
}
}
2.2 运行结果

2.3 代码解释
- Action11和Action12相对比较好理解。初始化数据到buffer1。
- Action2.1和Action2.2相对比较费解,他们同时接受buffer1作为输入,为什么最终的结果Buffer2没有产生重复? 最后由Action21,action22同时产生的buffer3为什么也没有重复?这就是GetConsumingEnumerable这个方法的功劳。这个方法会将buffer的数据分成多份给多个消费者,如果一个value已经被一个消费者获取,那么其他消费者将不会再拿到这个值。这就回答了为什么没有重复这个问题。
- 上面方法同时使用了多任务延续(ContinueWhenAll)对buffer的调用CompleteAdding方法:该方法非常重要,如果没有调用这个方法,程序会进入死锁,因为消费者(consumer)会处于一直的等待状态。
Parallel Programming-多消费者,多生产者同时运行并行的更多相关文章
- ParallelProgramming-多消费者,多生产者同时运行并行
在上一篇文章演示了并行的流水线操作(生产者和消费者并行同时执行),C#是通过BlockingCollection这个线程安全的对象作为Buffer,并且结合Task来实现的.但是上一篇文章有个缺陷,在 ...
- Java多线程消费者、生产者的基本思路
多线程主要考察的就是 线程的同步控制 生产者消费者的思路就是,当 一个线程执行时让另一个线程 挂起就行了 ThreadOne.ThreadTwo同时运行,添加一个变量在一个公共类(下边的Funct ...
- springcloud 实现简单的 消费者和生产者 模式(Restfule 的风格)
一.springcloud 实现简单的 消费者和生产者 模式(Restfule 的风格) 1.实现简单的消费者和生产者 springcloud使用的http协议进行传输数据,也就是说springclo ...
- Java程序设计之消费者和生产者
新建一个Break类,表示食物数量. public class Break { public static final int MAX = 10; //最多一次性煮十个面包 Stack<Inte ...
- Notes of Principles of Parallel Programming - TODO
0.1 TopicNotes of Lin C., Snyder L.. Principles of Parallel Programming. Beijing: China Machine Pres ...
- 4.3 Reduction代码(Heterogeneous Parallel Programming class lab)
首先添加上Heterogeneous Parallel Programming class 中 lab: Reduction的代码: myReduction.c // MP Reduction // ...
- Task Cancellation: Parallel Programming
http://beyondrelational.com/modules/2/blogs/79/posts/11524/task-cancellation-parallel-programming-ii ...
- java多线程-消费者和生产者模式
/* * 多线程-消费者和生产者模式 * 在实现消费者生产者模式的时候必须要具备两个前提,一是,必须访问的是一个共享资源,二是必须要有线程锁,且锁的是同一个对象 * */ /*资源类中定义了name( ...
- Samples for Parallel Programming with the .NET Framework
The .NET Framework 4 includes significant advancements for developers writing parallel and concurren ...
随机推荐
- Office Web Apps 2013对文档的精细定位
在一般情况下,我们使用Office Web Apps查看文档都是从第一页开始查看,不过在SharePoint搜索中,我们看到这样的结果: 这是2013搜索的一个新特性,可以深入定位到文档内部,支持PP ...
- jvm本身的多线程机制
1 多线程环境下的构造函数调用 构造函数本身并没有隐式的同步,因为各个线程构建的是自己的对象,它们之间是不存在竞争关系的. 2 class loader在load class时被了sychronize ...
- 洛谷 4035 [JSOI2008]球形空间产生器
题目戳这里 一句话题意 给你 n+1 个 n 维点,需要你求出这个n维球的球心.(n<=10) Solution 这个题目N维的话确实不好想,反正三维就已经把我搞懵了,所以只好拿二维类比. 首先 ...
- Java语言实现简单FTP软件------>辅助功能模块FTP站点管理的实现(十二)
1.FTP站点管理 点击"FTP站点管理"按钮,弹出对话框"FTP站点管理",如下图 1) 连接站点 在FTP站点管理面板上选好要连接的站点,点击"连 ...
- JSP 分页代码
jsp 分页模板 后台分页代码: 说明: 在 com.zc.domain 包下: PageBean.java 文件 package cn.itcast.customer.domain; impor ...
- JVM虚拟机调参
一.堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为 ...
- python 的for else语句
for中间不是break出来的,是正常循环完跳出循环的会执行else内的语句 while else语句也是如此 这个以前的常见语言没有,特此记录
- SpringBoot学习笔记(2):引入Spring Security
SpringBoot学习笔记(2):用Spring Security来保护你的应用 快速开始 本指南将引导您完成使用受Spring Security保护的资源创建简单Web应用程序的过程. 参考资料: ...
- error when start pyspark
ERROR spark.SparkContext: Error initializing SparkContext.java.lang.IllegalArgumentException: Requir ...
- 经典c语言题
1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 2. 写一个“标 ...