我们经常会遇到生产者消费者模式,比如前端各种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任务调度实现生产者消费者模式的更多相关文章

  1. 转:Task任务调度实现生产者消费者模式 (个人理解后文)

    纯属个人愚见.欢迎加入反驳(PiDou). 1.前文大致就是,利用Queue配置的一个TaskFactory任务调度器.实现生产者消费者模式的例子..首先我就试了 第一种 FIFO(先进先出)的配置. ...

  2. Celery 框架学习笔记(生产者消费者模式)

    生产者消费者模式 在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产 ...

  3. python3全栈开发-多进程的守护进程、进程同步、生产者消费者模式(重点)

    一.守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes a ...

  4. 第三节: List类型的介绍、生产者消费者模式、发布订阅模式

    一. List类型基础 1.介绍 它是一个双向链表,支持左进.左出.右进.右出,所以它即可以充当队列使用,也可以充当栈使用. (1). 队列:先进先出, 可以利用List左进右出,或者右进左出(Lis ...

  5. Java实现多线程生产者消费者模式的两种方法

    生产者消费者模式:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据.生产者生产一个,消费者消费一个,不断循环. 第一种实现方法,用BlockingQueue阻塞队 ...

  6. java多线程 生产者消费者模式

    package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...

  7. LabVIEW之生产者/消费者模式--队列操作 彭会锋

    LabVIEW之生产者/消费者模式--队列操作 彭会锋 本文章主要是对学习LabVIEW之生产者/消费者模式的学习笔记,其中涉及到同步控制技术-队列.事件.状态机.生产者-消费者模式,这几种技术在在本 ...

  8. Lucene.net站内搜索—4、搜索引擎第一版技术储备(简单介绍Log4Net、生产者消费者模式)

    目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...

  9. MVC异常日志生产者消费者模式记录(异常过滤器)

    生产者消费者模式 定义自己的异常过滤器并注册 namespace Eco.Web.App.Models { public class MyExceptionAttribute : HandleErro ...

随机推荐

  1. Beaglebone Black–I2C 接 BMP280 获取当前温度

    我有两个含温度传感的模块,一个是AOSONG 奥松电子的 AM2320 温度湿度,另一个是九轴里面的 Bosch BMP280.由于 AM2320 用 I2C MODBUS,直接用 I2C Tools ...

  2. SQL Server 查询表的记录数(3种方法,推荐第一种)

    http://blog.csdn.net/smahorse/article/details/8156483 --SQL Server 查询表的记录数 --one: 使用系统表. SELECT obje ...

  3. Linux信号基础

    Linux信号基础   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Linux进程基础一文中已经提到,Linux以进程为单位来 ...

  4. PHP-----二维数组和二分查找

    二维数组由行和列组成.由arr[$i][$j]表示,先后表示行和列,类似于坐标点. 打印二维数组-----通过两次遍历,第一次遍历每一行,第二次遍历每一行的具体元素,并且通过使用count($arr[ ...

  5. mysql的初识--DOS下的简单命令

    DOS下进入 1.通过程序中的mySQL的:MySQL 5.6 Command Line Client直接进入mySQL的命令行: 2.或者通过WIn+R-->输入cmd,然后C:等一层一层找到 ...

  6. php总结 --- 10. xml操作

    xml 和array互换 /** * 数组编码为XML * @param array $data 数据 * @return mixed 编码后数据 */ function xmlencode($dat ...

  7. 【Asp.net之旅】--数据绑定控件之Repeater

    http://blog.csdn.net/zhang_xinxiu/article/details/21872433

  8. js的常用api

    JavaScript常用API总结 原创 2016-10-02 story JavaScript 下面是我整理的一些JavaScript常用的API清单. 目录 元素查找 class操作 节点操作 属 ...

  9. Laravel 5 使用中的问题记录(持续更新)

    1.更新了blade模板却没有更新缓存 通过使用ftp上传文件到服务器,更新了blade模板,却没有更新缓存,经查,原因是系统时间的影响,通过ftp上传的模板文件修改时间与缓存文件的时间不一致,导致模 ...

  10. python--安装PIL

    PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了.PIL功能非常强大,但API却非常简单易用. 安装PIL 在Debian/Ubuntu Linux ...