转:Task任务调度实现生产者消费者模式
我们经常会遇到生产者消费者模式,比如前端各种UI操作事件触发后台逻辑等。在这种典型的应用场景中,我们可能会有4个业务处理逻辑(下文以P代表生产者,C代表消费者):
1. FIFO(先进先出)
P产生1,2,3,4,5,6,3,2
C处理顺序应为1,2,3,4,5,6,3,2
2.LIFO(后进先出)
P产生1,2,3,4,5,6,3,2
C处理顺序应为2,3,6,5,4,3,2,1
3.Dynamic FIFO(我定义为:去掉相同数据的FIFO, 如果产生的数据队列里已经有相同数据,后进的数据优先级高)
P产生1,2,3,4,5,6,3,2
C处理顺序为1,4,5,6,3,2
4.Dynamic LIFO(我定义为:去掉相同数据的LIFO, 如果产生的数据栈里已经有相同数据,后进的数据优先级高)
P产生1,2,3,4,5,6,3,2
C处理顺序为2,3,6,5,4,1
1,2情况为基本处理逻辑,3,4可能和我们实际场景有关系(包括:判断相同的逻辑可能不同、已存在和后续数据哪个优先级高)
C#中有个Task类进行异步操作,我们可以通过TaskScheduler类进行任务调度,实现上述的4种基本场景。
定义上述4种场景的通用接口以及其遍历类
public interface IScheduler : IEnumerable<Task >
{
void Add (Task t);
void Remove (Task t);
int Count { get; }
Task this [int index] { get; set ; }
}
public class SchedulerEnumerator : IEnumerator< Task>
{
private IScheduler _collection;
private int _currentIndex;
private Task _currentTask;
public SchedulerEnumerator (IScheduler collection)
{
_collection = collection ;
_currentIndex = -1;
_currentTask = default (Task);
}
public bool MoveNext()
{
//Avoids going beyond the end of the collection.
if (++_currentIndex >= _collection. Count)
{
return false ;
}
else
{
// Set current box to next item in collection.
_currentTask = _collection [_currentIndex];
}
return true ;
}
public void Reset() { _currentIndex = -1; }
void IDisposable .Dispose() { }
public Task Current
{
get { return _currentTask; }
}
object IEnumerator .Current
{
get { return Current; }
}
}
实现我们自己的任务调度类模板,可以通过T传递我们想要的队列类型
public class TaskSchedulerBase <T> : TaskScheduler
where T : IScheduler , new ()
{
private Thread _processThread;
private readonly object _lock = new object ();
public TaskSchedulerBase()
{
_processThread = new Thread (this.Process);
}
private void Process()
{
lock (_lock)
{
var tasks = GetScheduledTasks();
if (null != tasks)
{
foreach (var t in tasks)
{
TryExecuteTask(t);
TryDequeue(t);
}
}
}
}
protected override void QueueTask( Task task)
{
lock (_lock)
{
Scheduler.Add(task);
if (_processThread.ThreadState.Equals(ThreadState .Stopped))
{
_processThread = new Thread (Process);
}
if (!_processThread.IsAlive
&& !_processThread.ThreadState.Equals( ThreadState.Running))
{
try
{
_processThread.Start();
}
catch (System.Exception )
{
if (!_processThread.ThreadState.Equals(ThreadState .Running))
{
_processThread = new Thread (Process);
_processThread.Start();
}
}
}
}
}
protected override bool TryDequeue( Task task)
{
Scheduler.Remove(task);
return true ;
}
protected override IEnumerable< Task> GetScheduledTasks()
{
return Scheduler.ToArray();
}
protected override bool TryExecuteTaskInline( Task task, bool taskWasPreviouslyQueued)
{
if (taskWasPreviouslyQueued)
{
if (TryDequeue(task))
{
return base .TryExecuteTask(task);
}
else
{
return false ;
}
}
else
{
return base .TryExecuteTask(task);
}
}
private readonly T _scheduler = new T();
public T Scheduler
{
get
{
return _scheduler;
}
}
}
实现4种队列
1.FIFO
public class QueueScheduler : IScheduler
{
protected Queue <Task> _queue;
public QueueScheduler ()
{
_queue = new Queue< Task>();
}
public void Add( Task t )
{
if (!Contains (t))
{
_queue.Enqueue (t);
}
}
public void Remove( Task t )
{
_queue.Dequeue ();
}
public bool Contains( Task t )
{
bool found = false;
foreach (var task in _queue )
{
if (t .AsyncState != null && t .AsyncState. Equals(task .AsyncState))
{
found = true ;
break;
}
}
return found ;
}
public bool Contains( Task t , EqualityComparer< Task> comp )
{
throw new NotImplementedException();
}
public IEnumerator <Task> GetEnumerator()
{
return new SchedulerEnumerator( this);
}
IEnumerator IEnumerable .GetEnumerator()
{
return new SchedulerEnumerator( this);
}
public int Count
{
get { return _queue. Count; }
}
public Task this[ int index]
{
get { return (Task) _queue.ToArray ()[index]; }
set { _queue .ToArray()[index] = value; }
}
}
2.LIFO
public class StackScheduler : IScheduler
{
protected Stack <Task> _stack;
public StackScheduler ()
{
_stack = new Stack< Task>();
}
public void Add( Task t )
{
if (!Contains (t))
{
_stack.Push (t);
}
}
public void Remove( Task t )
{
_stack.Pop ();
}
public bool Contains( Task t )
{
bool found = false;
foreach (var task in _stack )
{
if (t .AsyncState != null && t .AsyncState. Equals(task .AsyncState))
{
found = true ;
break;
}
}
return found ;
}
public bool Contains( Task t , EqualityComparer< Task> comp )
{
throw new NotImplementedException();
}
public IEnumerator <Task> GetEnumerator()
{
return new SchedulerEnumerator( this);
}
IEnumerator IEnumerable .GetEnumerator()
{
return new SchedulerEnumerator( this);
}
public int Count
{
get { return _stack. Count; }
}
public Task this[ int index]
{
get { return (Task) _stack.ToArray ()[index]; }
set { _stack .ToArray()[index] = value; }
}
}
3.Dynamic FIFO
public class DynamicQueueScheduler : IScheduler
{
protected List <Task> _queue;
public DynamicQueueScheduler ()
{
_queue = new List< Task>();
}
public virtual void Add(Task t)
{
Task oldTask = null;
if (Contains (t, out oldTask ))
{
_queue.Remove (oldTask);
}
_queue.Add (t);
}
public virtual void Remove(Task t)
{
_queue.Remove (t);
}
public virtual bool Contains(Task t)
{
Task oldTask = null;
bool found = Contains( t, out oldTask);
return found ;
}
public virtual bool Contains(Task t, out Task oldTask)
{
bool found = false;
oldTask = null ;
foreach (var task in _queue )
{
if (t .AsyncState != null && t .AsyncState. Equals(task .AsyncState))
{
oldTask = task ;
found = true ;
break;
}
}
return found ;
}
public virtual bool Contains(Task t, EqualityComparer<Task > comp)
{
throw new NotImplementedException();
}
public IEnumerator <Task> GetEnumerator()
{
return new SchedulerEnumerator( this);
}
IEnumerator IEnumerable .GetEnumerator()
{
return new SchedulerEnumerator( this);
}
public int Count
{
get { return _queue. Count; }
}
public Task this[ int index]
{
get { return (Task) _queue[index]; }
set { _queue [index] = value; }
}
}
4.Dynamic LIFO
public class DynamicStackScheduler : IScheduler
{
protected List <Task> _queue;
public DynamicStackScheduler ()
{
_queue = new List< Task>();
}
public void Add( Task t )
{
Task oldTask = null;
if (Contains (t, out oldTask ))
{
_queue.Remove (oldTask);
}
_queue.Insert (0,t);
}
public void Remove( Task t )
{
_queue.Remove (t);
}
public bool Contains( Task t )
{
Task oldTask = null;
bool found = Contains( t, out oldTask);
return found ;
}
public bool Contains( Task t , out Task oldTask )
{
bool found = false;
oldTask = null ;
foreach (var task in _queue )
{
if (t .AsyncState != null && t .AsyncState. Equals(task .AsyncState))
{
oldTask = task ;
found = true ;
break;
}
}
return found ;
}
public bool Contains( Task t , EqualityComparer< Task> comp )
{
throw new NotImplementedException();
}
public IEnumerator <Task> GetEnumerator()
{
return new SchedulerEnumerator( this);
}
IEnumerator IEnumerable .GetEnumerator()
{
return new SchedulerEnumerator( this);
}
public int Count
{
get { return _queue. Count; }
}
public Task this[ int index]
{
get { return (Task) _queue[index]; }
set { _queue [index] = value; }
}
}
测试代码
class Program
{
static Queue <int> _queue = new Queue< int>();
//static TaskFactory _factory = new TaskFactory(new TaskSchedulerBase<QueueScheduler>());
//static TaskFactory _factory = new TaskFactory(new TaskSchedulerBase<StackScheduler>());
//static TaskFactory _factory = new TaskFactory(new TaskSchedulerBase<DynamicQueueScheduler>());
//static TaskFactory _factory = new TaskFactory(new TaskSchedulerBase<DynamicStackScheduler>());
static TaskFactory _factory = new TaskFactory (new TaskSchedulerBase<DynamicQueueScheduler >());
static void Main( string[] args )
{
var thread1 = new Thread(Producer );
var thread2 = new Thread(Consumer );
thread1.Start ();
thread2.Start ();
Console.ReadKey ();
}
static void Producer()
{
for (int i = 0; i < 7; i ++)
{
_queue.Enqueue (i);
}
_queue.Enqueue (3);
_queue.Enqueue (2);
}
static void Consumer()
{
while (true )
{
if (_queue .Count > 0)
{
foreach (var i in _queue )
{
_factory.StartNew ((s) =>
{
Console.Write ("{0} on thread {1} {2}\n", s,Thread.CurrentThread .ManagedThreadId,
DateTime.Now.ToLongTimeString());
}, i);
}
_queue.Clear ();
}
else
{
Thread.Sleep (1);
}
}
}
}
转:Task任务调度实现生产者消费者模式的更多相关文章
- 转:Task任务调度实现生产者消费者模式 (个人理解后文)
纯属个人愚见.欢迎加入反驳(PiDou). 1.前文大致就是,利用Queue配置的一个TaskFactory任务调度器.实现生产者消费者模式的例子..首先我就试了 第一种 FIFO(先进先出)的配置. ...
- Celery 框架学习笔记(生产者消费者模式)
生产者消费者模式 在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产 ...
- python3全栈开发-多进程的守护进程、进程同步、生产者消费者模式(重点)
一.守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes a ...
- 第三节: List类型的介绍、生产者消费者模式、发布订阅模式
一. List类型基础 1.介绍 它是一个双向链表,支持左进.左出.右进.右出,所以它即可以充当队列使用,也可以充当栈使用. (1). 队列:先进先出, 可以利用List左进右出,或者右进左出(Lis ...
- Java实现多线程生产者消费者模式的两种方法
生产者消费者模式:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据.生产者生产一个,消费者消费一个,不断循环. 第一种实现方法,用BlockingQueue阻塞队 ...
- java多线程 生产者消费者模式
package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...
- LabVIEW之生产者/消费者模式--队列操作 彭会锋
LabVIEW之生产者/消费者模式--队列操作 彭会锋 本文章主要是对学习LabVIEW之生产者/消费者模式的学习笔记,其中涉及到同步控制技术-队列.事件.状态机.生产者-消费者模式,这几种技术在在本 ...
- Lucene.net站内搜索—4、搜索引擎第一版技术储备(简单介绍Log4Net、生产者消费者模式)
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- MVC异常日志生产者消费者模式记录(异常过滤器)
生产者消费者模式 定义自己的异常过滤器并注册 namespace Eco.Web.App.Models { public class MyExceptionAttribute : HandleErro ...
随机推荐
- memcache内存估算整理
参考文章: http://blog.csdn.net/tonyxf121/article/details/7906428 http://zhihuzeye.com/archives/2361 memc ...
- STM32学习笔记(九) 外部中断,待机模式和事件唤醒
学会知识只需要不段的积累和提高,但是如何将知识系统的讲解出来就需要深入的认知和系统的了解.外部中断和事件学习难度并不高,不过涉及到STM32的电源控制部分,还是值得认真了解的,在本文中我将以实际代码为 ...
- sqlplus无密码登录TNS协议适配器错误
登录到sqlplus使用无密码登录用户时出现:TNS协议适配器错误 检查自己是否有多个数据库,可能默认登录的数据库服务没有启动,启动即可. 查看当前数据库名 select name from v$d ...
- laravel 中 与前端的一些事4 之合并压缩静态文件
合并压缩多个静态文件到一个文件里面,可以减少网站的http请求,稍微优化性能,提高网站的用户体验 使用elixir来实现: 敲命令 合并并压缩js和css文件
- windows下面安装casperjs
因为需要 就学习了一下casperjs,CasperJS是一个开源的导航脚本处理和测试工具,基于PhantomJS(前端自动化测试工具)编写.由于casperjs对PhantomJS的依赖性,所以需要 ...
- jsp项目与mysql链接
因为毕设是地下车库管理系统,所以打算学习jsp进行开发~ 今天主要是[新建网站项目+mysql链接],在此篇之前所做的工作:tomcat服务器配置,mysql数据库的安装与启用(在之后的开发中可以使用 ...
- socket编程与利用进程进行多并行连接
呈现一张基本的socket阻塞式模型,如下图: 一: 对于一对一的进行C/S回射: 服务端(server.c): #include<unistd.h> #include<stdio. ...
- oracle怎样用触发器将一张表的数据添加到另外一张表中
好吧,我就假设你两个表的数据结构相同吧create table TabA( address varchar2(50), press varchar2(50), city varchar2(50) )/ ...
- WinForm程序打包说明
如果使用的是VS2013需要下载并安装 Microsoft Visual Studio 2013 Installer Projects 下载地址:https://visualstudiogallery ...
- 解决ssh链接服务器超时自动断开的问题
为了安全性:ssh默认的连接超时时间很短:经常就是发个呆就断开了:事实上是可以修改超时时间的. 示例环境: 服务器:centos6.5 1:[root@iZ28qa8jt4uZ /]cp /etc/s ...