Extended Thread Pool(可扩展的线程池)

来源:互联网 发布:手机无缝拼图软件 编辑:程序博客网 时间:2024/05/01 19:00

Extended Thread Pool 的特征

  • IoC 支持(使用了Unity
  • 扩展队列
  • 扩展任务项
  • 限制了工作线程的最大数量
  • 动态线程分配
  • 线程优先级支持
  • 扩展日志

Extended Thread Pool的设计

  • ITaskItem 表示任务
  • ITaskQueue 表示任务的队列逻辑
  • ITaskQueueController 表示消费者和生产者之间的通信逻辑(线程安全)
  • WorkThread 表示线程执行
  • ExtendedThreadPool 控制线程的执行

让我们来深入了解每个类:

  • ITaskItem 表示要完成工作
    1.  public interface ITaskItem
    2.  {
    3.        ThreadPriority Priority { get; }
    4.        void DoWork();
    5.   }
  • ThreadPriority – WorkThread 的优先级,可以在每个任务中指定
  • ITaskQueue 另一个管理任务队列的接口
    1.     public interface ITaskQueue
    2.     {
    3.         int Count { get; }
    4.         void Enqueue(ITaskItem item);
    5.         ITaskItem Dequeue();
    6.     }
  • ITaskQueueController提供了消费者和生产者之间的通信逻辑
    1.     public interface ITaskQueueController : IDisposable
    2.     {
    3.         int ConsumersWaiting { get; }
    4.         void Enqueue(ITaskItem item);
    5.         ITaskItem Dequeue();
    6.     }

ITaskQueueController接口派生了两个队列控制对象:

  • DefaultTaskQueueController
  • BoundedTaskQueueController

Default Task Queue Controller

 

DefaultTaskQueueController对与ITaskQueue是线程安全的封装:

  1. public class DefaultTaskQueueController : TaskQueueControllerBase
  2. {
  3.     public DefaultTaskQueueController(ITaskQueue taskQueue)
  4.         : base(taskQueue)
  5.     {
  6.     }
  7.     #region Overrides of TaskQueueControllerBase
  8.     public override void Enqueue(ITaskItem item)
  9.     {
  10.         lock (_locker)
  11.         {
  12.             _taskQueue.Enqueue(item);
  13.             if (_consumersWaiting > 0)
  14.                 Monitor.PulseAll(_locker);
  15.         }
  16.     }
  17.     public override ITaskItem Dequeue()
  18.     {
  19.         ITaskItem taskItem;
  20.         lock (_locker)
  21.         {
  22.             while (_taskQueue.Count == 0 && !_isDispose)
  23.             {
  24.                 _consumersWaiting++;
  25.                 Monitor.Wait(_locker);
  26.                 _consumersWaiting--;
  27.             }
  28.             if (_isDispose)
  29.                 return null;
  30.             taskItem = _taskQueue.Dequeue();
  31.         }
  32.         return taskItem;
  33.     }
  34.     #endregion
  35. }

Bounded Task Queue Controller

BoundedTaskQueueController(线程安全)如果生产者任务或者创建项的任务比消费者的处理速度快,系统将会无限的消耗内存。BoundedTaskQueueController允许限制队列的大小来限制生产者的越界。 

  1. public class BoundedTaskQueueController : TaskQueueControllerBase
  2. {
  3.     private readonly int _maxTasksCount;
  4.     private int _producersWaiting;
  5.     public BoundedTaskQueueController(ITaskQueue taskQueue, int maxTasksCount)
  6.         : base(taskQueue)
  7.     {
  8.         if (maxTasksCount < 1)
  9.             throw new ArgumentException("MaxTasksCount should be greater 0");
  10.         _maxTasksCount = maxTasksCount;
  11.     }
  12.     public override void Enqueue(ITaskItem item)
  13.     {
  14.         lock (_locker)
  15.         {
  16.             while (_taskQueue.Count == (_maxTasksCount - 1) && !_isDispose)
  17.             {
  18.                 _producersWaiting++;
  19.                 Monitor.Wait(_locker);
  20.                 _producersWaiting--;
  21.             }
  22.             _taskQueue.Enqueue(item);
  23.             if (_consumersWaiting > 0)
  24.                 Monitor.PulseAll(_locker);
  25.         }
  26.     }
  27.     public override ITaskItem Dequeue()
  28.     {
  29.         ITaskItem taskItem;
  30.         lock (_locker)
  31.         {
  32.             while (_taskQueue.Count == 0 && !_isDispose)
  33.             {
  34.                 _consumersWaiting++;
  35.                 Monitor.Wait(_locker);
  36.                 _consumersWaiting--;
  37.             }
  38.             if (_isDispose)
  39.                 return null;
  40.             taskItem = _taskQueue.Dequeue();
  41.             if (_producersWaiting > 0)
  42.                 Monitor.PulseAll(_locker);
  43.         }
  44.         return taskItem;
  45.     }
  46. }

Extended Thread Pool

 

ExtendedThreadPool类管理接口ITaskQueueControllerAddTask方法用来添加任务到任务通道中去。如果最大的线程限制未达到并且ConsamersWaitin = 0WorkThread类的新实例将被创建。 

  1. public void AddTask(ITaskItem item)
  2. {
  3.     if (item.IsNull())
  4.         throw new ArgumentNullException("item");
  5.     if (!(Enum.IsDefined(typeof (ThreadPriority), item.Priority)))
  6.         throw new ArgumentException("priority");
  7.     TaskQueueController.Enqueue(item);
  8.     if (IsStartNewWorker())
  9.         CreateWorkThread();
  10. }

Work Thread

 

WorkThread类,执行任务项和提供日志记录的。 

  1. public void Start()
  2. {
  3.     while (_isRun)
  4.     {
  5.         try
  6.         {
  7.             ITaskItem item = _taskQueueController.Dequeue();
  8.             if (item.IsNull())
  9.                 continue;
  10.             DoWork(item);
  11.         }
  12.         catch (Exception ex)
  13.         {
  14.             _logger.Error(ex.Message);
  15.         }
  16.     }
  17. }

Thread Pool Extensibility

 

ExtendedThreadPool类提供了Ioc支持,ITaskQueueController接口标记了Dependency属性。 

  1. [Dependency]
  2. public ITaskQueueController TaskQueueController { private getset; }

如果你需要更加强大的任务队列,就必须实现ITaskQueue接口,并不需要担心线程安全的问题;也可以创建ITaskQueueController。我使用Unity来配置ExtendedThreadPool

 

 

 

 

例子

 

在其中一个项目中,我使用了multi-threading进行MSMQ交互。SampleTask派生了接口ITaskItem,可以从项目CoreDefaultMsmqSample中了解详情。 

  1. public void DoWork()
  2. {
  3.     using (var transaction = new MessageQueueTransaction())
  4.     {
  5.         try
  6.         {
  7.             transaction.Begin();
  8.             Message msmqMessage = 
  9.               _queue.Receive(TimeSpan.FromMilliseconds(500), transaction);
  10.             if (msmqMessage != null)
  11.             {
  12.                 var message = (ExternalMessage) msmqMessage.Body;
  13.                 LogManager.GetLogger(GetType()).Info("Task has been " + 
  14.                            "done, info {0}".FormatWith(message.Data));
  15.                 //Do work
  16.                 Thread.Sleep(1000);
  17.             }
  18.         }
  19.         catch (Exception ex)
  20.         {
  21.             transaction.Abort();
  22.             LogManager.GetLogger(GetType()).Error(ex.Message);
  23.             return;
  24.         }
  25.         transaction.Commit();
  26.     }
  27. }

总结

作者考虑到了线程池的可配置性和扩展性,在引用这些代码后,写出的线程应用会非常简洁,且不需要考虑线程之间的复杂操作.如果,你觉得有写模块是你不需要的,比如日志模块或者IoC模块(这是什么模块我也不清楚),可以自行把代码删除掉,希望原作者会继续他的思路完善这个框架.

原创粉丝点击