转: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 ...
随机推荐
- "旋转的风车"----windows(GDI)绘图
这正是秋季将尽, 冬季未到的时节. 黄土高坡上已滚起了漫天黄沙, 而这里却是万里晴空如练! 风, 丝丝入骨! 未央柳即将枯死的枝条,仍在挣扎. 街道两旁清一色的银杏树叶, 金灿耀眼. 耀的令人感动, ...
- AC自动机模板
贴份模板 胡大神和崔大神的组合模板 #include <iostream> #include<cstdio> #include<cstring> #include& ...
- DB2表分区删除
近日,由于部门数据库读库空间过小,提出删除掉两个月之前日志表的分区(数据库分区是按时间月分区),记述如下: 上网搜索资料发现删除表分区大概分这么几步: 1.查询需要删除掉的分区: select t.D ...
- eclipse 本地项目提交到远程库以及从远程库中添加项目 ---git
本地项目提交到远程库 1.右击项目->team->share project 2.选择本地库 从远处库中的项目拉到本地 1.右击项目->import项目
- 第一章 企业项目开发--maven+springmvc+spring+mybatis+velocity整合
说明:本系列文章主要是对自己在一家大型互联网公司实习的过程中对所学知识的总结!参与的是实际中使用的上线项目. 代码的github地址:https://github.com/zhaojigang/ssm ...
- 老麦看点:SEO高手的两大秘诀
一.技术真的是主导因素吗? 很多人站长朋友操作一段网站之后,发现自己的排名还是在渺渺无期,真可谓:“众里寻排名千百度,可是排名却不在阑珊处”,于是我们开始怀疑自己,怀疑自己的技术等,但是我们静下心里仔 ...
- GCC选项 –I,-l,-L
-I:指定第一个寻找头文件的目录 -L:指定第一个寻找库文件的目录 -l:表示在库文件目录中寻找指定的动态库文件 例: gcc –o hello hello.c –I /home/hello/incl ...
- Winform开发框架之系统登录实现
在业务系统的操作过程中,有时候,用户需要切换用户进行重新登录,这种情况有时候是因为一个人管理多个用户账号,希望通过不同的账号登录进行管理不同的资料,另一种情况是酒店的换班操作,另一个人接替前面的人进行 ...
- OC基础--Hello Shit
/* Foundation.h为主头文件, 主头文件中又拷贝了该工具箱中所有工具的头文件, 我们只需要导入主头文件就可以使用该工具箱中所有的工具, 避免了每次使用都要导入一个对应的头文件 工具箱的 ...
- SharePoint\O365 CSOM操作"请求访问设置"功能
博客地址:http://blog.csdn.net/FoxDave 请求访问设置是在SharePoint网站权限菜单中的一个功能,如下图: 它用来设置成员是否可以共享网站以及个别文件和文件夹,是否允许 ...