利用System.Thread.Timer优化Active Object模式执行效率[zz]

时间:2022-04-14 17:34:08

http://zhenyulu.cnblogs.com/articles/27432.html
源代码下载:未经改造的ActiveObject利用Timer对象改造后的ActiveObject

关于ActiveOjbect模式,第一次是在Robert C. Martin的《敏捷软件开发-原则、模式与实践》一书中看到的,后来找到了ActiveObject的出处:Lavender的《Active Object An Object Behavioral Pattern for Concurrent Programming》,才发现Active Object模式比我想象中的还要复杂,功能还要强大。它模拟实现了一种异步的、多线程的控制模式,为许多工业系统提供了一个简单的多任务核心。

《敏捷软件开发》中给出了一个Java实现的例子,从一个侧面表现了ActiveObject的使用方法。该例子通过ActiveObject引擎对命令队列中的命令进行循环处理,实现了命令的延时调用。其关键算法可以描述如下:

1、构造一延时命令,该延时命令将包含一任务并记录开始时间
2、将该延时命令放入队列。
3、从队列中取出一命令,若是延时命令,则判断是否到时,若尚未到时,则转向第2步。若到时,则释放出包含的任务到队列中。
4、判断是否是循环延时任务,如果是,则重新记录开始时间,并转向第 2 步。
5、转向第 3 步。

我将其改为了C#代码,关键代码如下:

利用System.Thread.Timer优化Active Object模式执行效率[zz]public   void  Execute()
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]  DateTime currentTime 
= DateTime.Now;
利用System.Thread.Timer优化Active Object模式执行效率[zz]  TimeSpan ts 
= currentTime - startTime;
利用System.Thread.Timer优化Active Object模式执行效率[zz]  
if(!started)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]  
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]    started 
= true;
利用System.Thread.Timer优化Active Object模式执行效率[zz]    startTime 
= currentTime;
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ActiveObjectEngine.addCommand(
this);
利用System.Thread.Timer优化Active Object模式执行效率[zz]  }

利用System.Thread.Timer优化Active Object模式执行效率[zz]  
else if(ts.TotalMilliseconds < sleepTime)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]  
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ActiveObjectEngine.addCommand(
this);
利用System.Thread.Timer优化Active Object模式执行效率[zz]  }

利用System.Thread.Timer优化Active Object模式执行效率[zz]  
else
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]  
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ActiveObjectEngine.addCommand(InnerTask);
利用System.Thread.Timer优化Active Object模式执行效率[zz]    
if(repeat)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]    
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]      
this.startTime = DateTime.Now;
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.addCommand(
this);
利用System.Thread.Timer优化Active Object模式执行效率[zz]    }

利用System.Thread.Timer优化Active Object模式执行效率[zz]  }

利用System.Thread.Timer优化Active Object模式执行效率[zz]}

下面是用Together生成的UML图:
利用System.Thread.Timer优化Active Object模式执行效率[zz]

整个C#源代码可以从这里下载(.net 1.1下调试通过)

在该代码的应用中发现,一旦使用上该模式,CPU的占用率就达到了100%。也难怪,在任务比较轻的情况下,ActiveObject引擎绝大多数的时间都是在做一些无用功:从队列取出Command,看看是否到时,没有的话再把它放回到队列中。这些无用功占用了大量的CPU时间。即使创建一个新线程运行引擎,将线程的优先级别设置为ThreadPriority.BelowNormal,也避免不了CPU占用100%的问题。只不过此时用户不会感受到有任何迟滞而已(因为线程的优先级是BelowNormal)。

至此,能否更为有效的使用ActiveObject模式成了项目需要解决的一个关键问题。Windows中的Timer控件给了我一些启发:Timer控件可以定时触发事件,但从来不占用大量的CPU时间。如果简单的周期性任务,使用Timer非常简便(例如:每秒更新一下窗口上时钟的显示),但面对动态增加的,变化的周期性任务,使用Timer控件就显得有些麻烦(例如:每秒更新时间显示、每1.7秒读取一个数据、每2.3秒发送一条消息....),我们很容易想象到通过动态添加删除Timer控件来达到上述目的所面临的麻烦。如果能够将ActiveObject模式与Timer的优点结合起来,就可以构建一个高效、灵活的ActiveObject实现方案。下面是我的实现方案:

1、构造一Timer对象
2、遍历队列,执行已经到时的任务并计算距离最近一次事件触发还需多少时间
3、根据步骤 2 的结果设置Timer对象的下一次触发时间
4、Timer对象触发事件 2

通过将整个过程置于一个单独线程中执行,并在ActiveObject引擎空闲的时候,用WaitOne方法归还CPU占用以达到降低CPU占用率的问题。关键代码如下:

利用System.Thread.Timer优化Active Object模式执行效率[zz]private   static   bool  Stoped  =   true ;
利用System.Thread.Timer优化Active Object模式执行效率[zz]
private   static   readonly  TimeSpan MaxTimeSpan  =  TimeSpan.FromMilliseconds( int .MaxValue);
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]
private   static  Thread thread;
利用System.Thread.Timer优化Active Object模式执行效率[zz]
private   static  ArrayList itsCommands  =   new  ArrayList();
利用System.Thread.Timer优化Active Object模式执行效率[zz]
private   static  TimerCallback timerDelegate  =   new  TimerCallback(ActiveObjectEngine.CallOnTime);
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]
private   static  ManualResetEvent manualEvent  =   new  ManualResetEvent( false );
利用System.Thread.Timer优化Active Object模式执行效率[zz]
private   static  Timer stateTimer  =   new  Timer(timerDelegate, manualEvent, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
//  由定时器触发的方法
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
private   static   void  CallOnTime(Object stateInfo)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]  ((ManualResetEvent)stateInfo).Set();
利用System.Thread.Timer优化Active Object模式执行效率[zz]}

利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
//  启动ActiveObject引擎
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
public   static   void  Start()
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]  Stoped 
= false;
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]  thread 
= new Thread(new ThreadStart(ActiveObjectEngine.Run));
利用System.Thread.Timer优化Active Object模式执行效率[zz]  thread.IsBackground 
= true;
利用System.Thread.Timer优化Active Object模式执行效率[zz]  thread.Priority 
= ThreadPriority.BelowNormal;
利用System.Thread.Timer优化Active Object模式执行效率[zz]  thread.Start();
利用System.Thread.Timer优化Active Object模式执行效率[zz]}

利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
//  线程入口点
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
private   static   void  Run()
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]  
while(!Stoped)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]  
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]    stateTimer.Change(GetNextRunTime(), MaxTimeSpan);
利用System.Thread.Timer优化Active Object模式执行效率[zz]    manualEvent.Reset();
利用System.Thread.Timer优化Active Object模式执行效率[zz]    manualEvent.WaitOne();
利用System.Thread.Timer优化Active Object模式执行效率[zz]  }

利用System.Thread.Timer优化Active Object模式执行效率[zz]}

利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
//  获取下一个需要触发事件的时间
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
private   static  TimeSpan GetNextRunTime()
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]  TimeSpan ts, nextRunTime 
= MaxTimeSpan;
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]  
lock(itsCommands)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]  
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]    
if(itsCommands.Count == 0)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]    
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]      Stop();
利用System.Thread.Timer优化Active Object模式执行效率[zz]      
return TimeSpan.FromMilliseconds(System.Threading.Timeout.Infinite);
利用System.Thread.Timer优化Active Object模式执行效率[zz]    }

利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]    
foreach(ICommand cmd in itsCommands)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]    
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ts 
= cmd.Execute();
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]      
if(!cmd.Active)
利用System.Thread.Timer优化Active Object模式执行效率[zz]        itsCommands.Remove(cmd);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      
else if(ts < nextRunTime)
利用System.Thread.Timer优化Active Object模式执行效率[zz]        nextRunTime 
= ts;
利用System.Thread.Timer优化Active Object模式执行效率[zz]    }

利用System.Thread.Timer优化Active Object模式执行效率[zz]  }

利用System.Thread.Timer优化Active Object模式执行效率[zz]  
return nextRunTime;
利用System.Thread.Timer优化Active Object模式执行效率[zz]}

利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
//  向ActiveObject引擎中添加定时任务
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
public   static   void  addCommand(ICommand c)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]  
lock(itsCommands)
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]  
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]    itsCommands.Add(c);
利用System.Thread.Timer优化Active Object模式执行效率[zz]    stateTimer.Change(GetNextRunTime(), MaxTimeSpan);
利用System.Thread.Timer优化Active Object模式执行效率[zz]  }
  
利用System.Thread.Timer优化Active Object模式执行效率[zz]}

利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
//  停止ActiveObject引擎
利用System.Thread.Timer优化Active Object模式执行效率[zz]
// =====================================
利用System.Thread.Timer优化Active Object模式执行效率[zz]
public   static   void  Stop()
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]  Stoped 
= true;
利用System.Thread.Timer优化Active Object模式执行效率[zz]  manualEvent.Set();
利用System.Thread.Timer优化Active Object模式执行效率[zz]  stateTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
利用System.Thread.Timer优化Active Object模式执行效率[zz]  Thread.Sleep(
500);
利用System.Thread.Timer优化Active Object模式执行效率[zz]}

改造后的C#源代码可以从这里下载。修改后的ActiveObject模式UML图如下:

利用System.Thread.Timer优化Active Object模式执行效率[zz]

经过测试,改造后的ActiveObject引擎运行时CPU占用率急剧下降,在我的机器上平均CPU占用率只有不到2%,这大大提高了系统执行效率。

测试代码如下:

利用System.Thread.Timer优化Active Object模式执行效率[zz]using  System;
利用System.Thread.Timer优化Active Object模式执行效率[zz]
using  System.Threading;
利用System.Thread.Timer优化Active Object模式执行效率[zz]
using  NUnit.Framework;
利用System.Thread.Timer优化Active Object模式执行效率[zz]
using  TimedSchedule;
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]
namespace  TestTimedSchedule
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]  [TestFixture] 
利用System.Thread.Timer优化Active Object模式执行效率[zz]  
public class TimedSchedule_Test
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]  
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ICommand task1 
= new TestCommand("Task 1");
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ICommand task2 
= new TestCommand("Task 2");
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ICommand task3 
= new TestCommand("Task 3");
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ICommand task4 
= new TestCommand("Task 4");
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ICommand task5 
= new TestCommand("Task 5");
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ICommand task6 
= new TestCommand("Task 6");
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]    ActiveObjectEngine engine 
= new ActiveObjectEngine();
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]    [Test]
利用System.Thread.Timer优化Active Object模式执行效率[zz]    
public void TestScheduledCommand() 
利用System.Thread.Timer优化Active Object模式执行效率[zz]利用System.Thread.Timer优化Active Object模式执行效率[zz]    
{
利用System.Thread.Timer优化Active Object模式执行效率[zz]      Console.WriteLine(
" ============= Test ScheduledCommand =============");
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ScheduledCommand sc1 
= new ScheduledCommand(TimeSpan.FromMilliseconds(500), task1, true);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ScheduledCommand sc2 
= new ScheduledCommand(TimeSpan.FromMilliseconds(700), task2, true);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ScheduledCommand sc3 
= new ScheduledCommand(TimeSpan.FromMilliseconds(1100), task3, true);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ScheduledCommand sc4 
= new ScheduledCommand(TimeSpan.FromMilliseconds(900), task4, true);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ScheduledCommand sc5 
= new ScheduledCommand(TimeSpan.FromMilliseconds(1800), task5, true);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ScheduledCommand sc6 
= new ScheduledCommand(TimeSpan.FromMilliseconds(2100), task6, true);
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.addCommand(sc1);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.addCommand(sc2);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.addCommand(sc3);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.addCommand(sc4);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.addCommand(sc5);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.addCommand(sc6);
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.Start();
利用System.Thread.Timer优化Active Object模式执行效率[zz]      Thread.Sleep(
5000);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.Stop();
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]      Console.WriteLine(
" ======================================== ");
利用System.Thread.Timer优化Active Object模式执行效率[zz]
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.Start();
利用System.Thread.Timer优化Active Object模式执行效率[zz]      Thread.Sleep(
5000);
利用System.Thread.Timer优化Active Object模式执行效率[zz]      ActiveObjectEngine.Terminate();
利用System.Thread.Timer优化Active Object模式执行效率[zz]    }

利用System.Thread.Timer优化Active Object模式执行效率[zz]  }

利用System.Thread.Timer优化Active Object模式执行效率[zz]}