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

本文是翻译CodeProject上的一篇文章的,由于自己水平有限,许多地方有谬误.希望大家指正.在这之前,我也不知道这片文章是否有被翻译过,只是自己在学习线程池的时候发现了这篇好文章(原文地址:http://www.codeproject.com/KB/threads/ExtendedThreadPool.aspx),就顺便翻译了下.并下在了源码调试了下,感觉原作者确实有些先进的思路.本篇翻译的目的是想在这个基础上了解下线程池的应用和扩展.

源码可以到原地址去下载,要注册用户的哦^0^

下面是正文:

 

 

 

前言

 

线程池的类型有许多:Smart线程池, BlackHen.Threading,但是没有一个线程池支持扩展,所有的线程池的编码都是有难度的,工作起来又有一定难度。我尽力解决以下问题:

  • 线程池的可扩展和可配置
  • 线程池应用尽可能简单化

因此,我创建了Extended Thread Pool(作者有意思把该项目作为开源发展)。此线程池是以C# 3.0环境下创建的。

 

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模块(这是什么模块我也不清楚),可以自行把代码删除掉,希望原作者会继续他的思路完善这个框架.

    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 1
      评论

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论 1
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值