贝贝花花包包店,精品555皮具,钱夹,皮夹

字体: | 推荐给好友 上一篇 | 下一篇

ACE程序员教程-第5章 任务和主动对象:并发编程模式

发布: 2008-6-13 14:26 | 作者: Umar Syyid | 来源: 转载 | 查看: 240次

 

5任务主动对象Active Object):并发编程模式

  这一章介绍前面提到过的ACE_Task类,另外还介绍了主动对象模式。基本上这一章将涵盖两个主题。首先,它将讲述怎样将ACE_Task构造作为高级面向对象机制使用,用以编写多线程程序。其次,它将讨论怎样在主动对象模式[II]中使用ACE_Task

 

5.1主动对象

  那么到底什么是主动对象呢?传统上,所有的对象都是被动的代码段,对象中的代码是在对它发出方法调用的线程中执行的。也就是,调用线程(calling threads)被“借出”,以执行被动对象的方法。

  而主动对象却不一样。这些对象持有它们自己的线程(甚或多个线程),并将这个线程用于执行对它们的任何方法的调用。因而,如果你想象一个传统对象,在里面封装了一个线程(或多个线程),你就得到了一个主动对象。

  例如,设想对象“A”已在你的程序的main()函数中被实例化。当你的程序启动时,OS创建一个线程,以从main()函数开始执行。如果你调用对象A的任何方法,该线程将“流过”那个方法,并执行其中的代码。一旦执行完成,该线程返回调用该方法的点并继续它的执行。但是,如果”A”是主动对象,事情就不是这样了。在这种情况下,主线程不会被主动对象借用。相反,当”A”的方法被调用时,方法的执行发生在主动对象持有的线程中。另一种思考方法:如果调用的是被动对象的方法(常规对象),调用会阻塞(同步的);而另一方面,如果调用的是主动对象的方法,调用不会阻塞(异步的)。

 

5.2 ACE_Task

  ACE_TaskACE中的任务或主动对象“处理结构”的基类。在ACE中使用了此类来实现主动对象模式。所有希望成为“主动对象”的对象都必须从此类派生。你也可以把ACE_TASK看作是更高级的、更为面向对象的线程类。

  当我们在前一章中使用ACE_Thread包装时,你一定已经注意到了一些“不好”之处。那一章中的大多数程序都被分解为函数、而不是对象。这是因为ACE_Thread包装需要一个全局函数名、或是静态方法作为参数。随后该函数(静态方法)就被用作所派生的线程的“启动点”。这自然就使得程序员要为每个线程写一个函数。如我们已经看到的,这可能会导致非面向对象的程序分解。

  相反,ACE_Task处理的是对象,因而在构造OO程序时更便于思考。因此,在大多数情况下,当你需要构建多线程程序时,较好的选择是使用ACE_Task的子类。这样做有若干好处。首要的是刚刚所提到的,这可以产生更好的OO软件。其次,你不必操心你的线程入口是否是静态的,因为ACE_Task的入口是一个常规的成员函数。而且,我们会看到ACE_Task还包括了一种用于与其他任务进行通信的易于使用的机制。

  重申刚才所说的,ACE_Task可用作:

  • 更高级的线程(我们称之为任务)。
  • 主动对象模式中的主动对象。

5.2.1任务的结构

  ACE_Task的结构在本质上与基于Actor的系统[III]中的“Actor”的结构相类似。该结构如下所示:

 

 

5-1任务结构示意图

 

5-1说明每个任务都含有一或多个线程,以及一个底层消息队列。各个任务通过这些消息队列进行通信。但是,消息队列并非是程序员需要关注的对象。发送任务可以使用putq()调用来将消息插入到另一任务的消息队列中。随后接收任务就可以通过使用getq()调用来从它自己的消息队列里将消息提取出来。

  因而,你可以设想一个系统,由多个自治的任务(或主动对象)构成,这些任务通过它们的消息队列相互通信。这样的体系结构有助于大大简化多线程程序的编程模型。

 

5.2.2创建和使用任务

  如上面所提到的,要创建任务或主动对象,你必须从ACE_Task类派生子类。在子类派生之后,必须采取以下步骤:

 

  • 实现服务初始化和终止方法:open()方法应该包含所有专属于任务的初始化代码。其中可能包括诸如连接控制块、锁和内存这样的资源。close()方法是相应的终止方法。
  • 调用启用(Activation)方法:在主动对象实例化后,你必须通过调用activate()启用它。要在主动对象中创建的线程的数目,以及其他一些参数,被传递给activate()方法。activate()方法会使svc()方法成为所有它生成的线程的启动点。
  • 实现服务专有的处理方法:如上面所提到的,在主动对象被启用后,各个新线程在svc()方法中启动。应用开发者必须在子类中定义此方法。

 

  下面的例子演示怎样去创建任务:

 

5-1

#include "ace/OS.h"

#include "ace/Task.h"

 

class TaskOne: public ACE_Task

{

public:

//Implement the Service Initialization and Termination methods

int open(void*)

{

ACE_DEBUG((LM_DEBUG,"(%t) Active Object opened \n"));

 

//Activate the object with a thread in it.

activate();

 

return 0;

}

 

int close(u_long)

{

ACE_DEBUG((LM_DEBUG, "(%t) Active Object being closed down \n"));

return 0;

}

 

int svc(void)

{

ACE_DEBUG((LM_DEBUG,

"(%t) This is being done in a separate thread \n"));

 

// do thread specific work here

//.......

//.......

return 0;

}

};

 

int main(int argc, char *argv[])

{

//Create the task

TaskOne *one=new TaskOne;

 

//Start up the task

one->open(0);

 

//wait for all the tasks to exit

ACE_Thread_Manager::instance()->wait();

ACE_DEBUG((LM_DEBUG,"(%t) Main Task ends \n"));

}

 

上面的例子演示怎样把ACE_Task当作更高级的线程来使用。在例子中,TaskOne类派生自ACE_Task,并实现了open()close()svc()方法。在此任务对象实例化后,程序就调用它的open()方法。该方法依次调用activate()方法,致使一个新线程被派生和启动。该线程的入口是svc()方法。主线程等待主动对象线程终止,然后就退出进程。

TAG: 任务 主动对象 Active Object

41/41234>
 

评分:0

我来说两句

seccode