java主动对象模式的作用,主动对象模式-GilBert1987-ChinaUnix博客

参考:《ACE自适配通信环境中文技术文档》1.主动对象模式介绍

主动对象模式用于降低方法执行和方法调用之间的耦合。该模式描述了另外一种更为透明的任务间通信方法。

该模式使用ACE_Task类作为主动对象。在这个对象上调用方法时,它就像是常规对象一样。就是说,方法调用是通过同样的->操作符来完成的,其不同在于这些方法的执行发生于封装在ACE_Task中的线程内。

2.主动对象模式工作原理

2.1主动对象模式的参与者

1.主动对象(基于ACE_Task)。

2.ACE_Activation_Queue

3.若干ACE_Method_Object(主动对象的每个方法都需要有一个方法对象)。

4.若干ACE_Future对象(每个要返回结果的方法都需要这样一个对象)。

2.2主动对象模式的参与者的具体工作

1.ACE_Task创建和封装线程

2.ACE_Method_Object

必须为所有要从客户(框架的使用者)异步调用的方法编写方法对象。每个方法对象都派生自ACE_Method_Object,并会实现它的call()方法(call方法必须包含1.执行在主动对象中实际编写的方法,2.设置返回值)。每个方法对象还维护上下文信息(包括方法所对应的主动对象的引用,方法的参数的引用和返回值Future对象等)可以把方法对象看作是方法调用的“罩子”(closure)。客户发出方法调用,使得相应的方法对象被实例化,并被放入启用队列(activation queue)中。方法对象是命令(Command)模式的一种形式。

3.ACE_Activation_Queue

ACE_Activation_Queue是一个队列,方法对象在等待执行时被放入其中。因而启用队列中含有所有等待调用的方法(以方法对象的形式)。封装在ACE_Task中的线程保持阻塞,等待任何方法对象被放入启用队列。一旦有方法对象被放入,任务就将该方法对象取出,并调用它的call()方法。call()方法应该随即调用该方法在ACE_Task中的相应实现。在方法实现返回后,call()方法在ACE_Future对象中设置(set())所获得的结果。

4.ACE_Future

使用ACE_Future对象获取它在主动对象上发出的任何异步操作的结果。一旦客户发出异步调用,立即就会返回一个ACE_Future对象。于是客户就可以在任何它喜欢的时候去尝试从“期货”(future)对象中获取结果。如果客户试图在结果被设置之前从期货对象中提取结果:使用get()方法,客户将会阻塞。如果客户不希望阻塞,它可以通过使用ready()调用来轮询(poll)期货对象(ready()方法检查相应的结果的指针是否为空,为空,NotReady,不为空,Ready)。如果结果已被设置,该方法返回1;否则就返回0。ACE_Future对象基于“多态期货”(polymorphic futures)的概念。

///

3.例子

下面的例子演示主动对象模式是怎样实现的。在此例中,主动对象是一个“Logger”(日志记录器)对象。Logger使用慢速的I/O系统来记录发送给它的消息。因为此I/O系统很慢,我们不希望主应用任务的执行因为相对来说并非紧急的日志记录而减慢。为了防止此情况的发生,并且允许程序员像发出普通的方法调用那样发出日志调用,我们使用了主动对象模式。

//Main.CPP

#pragma comment(lib,"ACEd.lib")

#include "ace/Future.h"

#include "ace/OS.h"

#include "ace/Log_Msg.h"

#include "ace/Thread_Manager.h"

#include "Log.h"

typedef unsigned long u_long;

int main (int, char *[])

{

//创建一个Logger的Task的任务

Logger * logger = new Logger;

//ACE_Future 对象记录函数的返回值

ACE_Future logresult;

ACE_Future name;

//启动Logger任务(线程)

logger->open(0);

//在Logger上记录一些信息

size_t n_loops = 5;

for (size_t i = 0; i < n_loops; i++)

{

char * msg= new char[50];

ACE_DEBUG ((LM_DEBUG,"(%t)Issuing a non-blocking logging call\n"));

ACE_OS::sprintf(msg, "(%t)This is iteration %d", i);

logresult= logger->logMsg(msg);

}

ACE_DEBUG((LM_DEBUG,"(%t)Invoked all the log calls and can now continue with other work \n"));

//Do some work over here...    //....

//Find out the name of the logging task

name = logger->name();

//Check to "see" if the result of the name() call is available

if(name.ready())

ACE_DEBUG((LM_DEBUG,"(%t)Name is ready!\n"));

else

ACE_DEBUG((LM_DEBUG,"(%t)Blocking till I get the result of that call \n"));

//obtain the underlying result from the future object.

const char* task_name;

name.get(task_name);//同步

ACE_DEBUG ((LM_DEBUG,"(%t)==> The name of the task is: %s\n\n\n",));

//Wait for all threads to exit.

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

getchar();

return 0;

}

///

Log.h==>主动对象

#pragma once

#include "ace/Task.h"

#include "ace/Future.h"

#include "ACE/Activation_Queue.h"

class Logger: public ACE_Task

{

public:

//Initialization and termination methods

Logger();

virtual ~Logger(void);

virtual int open (void *);

virtual int close (u_long flags = 0);

//The entry point for all threads created in the Logger

virtual int svc (void);

///

//Methods which can be invoked by client asynchronously.

///

//Log message

ACE_Future logMsg(const char* msg);

//Return the name of the Task

ACE_Future name (void);

///

//Actual implementation methods for the Logger

///

u_long logMsg_i(const char *msg);

const char * name_i();

private:

char *name_;

ACE_Activation_Queue activation_queue_;

};

Log.cpp==>主动对象

#pragma once

#include "Log.h"

#include "LogMsgMo.h"

#include "Name_Mo.h"

Logger::Logger()

{

this->name_= new char[sizeof("Worker")];

ACE_OS:strcpy(name_,"Worker");

}

//Destructor

Logger::~Logger(void)

{

delete this->name_;

}

//The open method where the active object is activated

int Logger::open (void *)

{

ACE_DEBUG ((LM_DEBUG, "(%t) Logger %s open\n", this->name_));

return this->activate (THR_NEW_LWP);

}

//Called then the Logger task is destroyed.

int Logger::close (u_long flags)

{

ACE_DEBUG((LM_DEBUG, "(%t)Closing Logger \n"));

return 0;

}

/*The svc() method is the starting point for the thread created in theLogger active object. The thread created will run in an infinite loopwaiting for method objects to be enqueued on the private activationqueue. Once a method object is inserted onto the activation queue thethread wakes up, dequeues the method object and then invokes thecall() method on the method object it just dequeued. If there are nomethod objects on the activation queue, the task blocks and fallsasleep.*/

int Logger::svc (void)

{

while(1)

{

// Dequeue the next method object (we use an auto //pointer in case an exception is thrown in the ).

auto_ptr mo(this->activation_queue_.dequeue ());

ACE_DEBUG ((LM_DEBUG, "(%t) calling method object\n"));

// Call it.

if (mo->call () == -1)

break;

// Destructor automatically deletes it.

}

return 0;

}

//

//Methods which are invoked by client and execute asynchronously.

//

//Log this message

ACE_Future Logger::logMsg(const char* msg)

{

ACE_Future resultant_future;

//Create and enqueue method object onto the activation queue

this->activation_queue_.enqueue

(new logMsg_MO(this,msg,resultant_future));

return resultant_future;

}

//Return the name of the Task

ACE_Future Logger::name (void)

{

ACE_Future resultant_future;

//Create and enqueue onto the activation queue

this->activation_queue_.enqueue(new name_MO(this, resultant_future));

return resultant_future;

}

///

//Actual implementation methods for the Logger

///

u_long Logger::logMsg_i(const char *msg)

{

ACE_DEBUG((LM_DEBUG,"(%t)Logged: %s\n",msg));

//Go to sleep for a while to simulate slow I/O device

ACE_OS::sleep(2);

return 10;

}

const char * Logger::name_i()

{

ACE_DEBUG((LM_DEBUG,"(%t) Getting Name:...\n"));

//Go to sleep for a while to simulate slow I/O device

ACE_OS::sleep(2);

return name_;

}

下面两个类是方法对象

logMsg_MO.h==>向日志系统中写入文件

#pragma once

#include "ace/Method_Object.h"

#include "ace/Future.h"

#include "Log.h"

class logMsg_MO: public ACE_Method_Object

{

public:

//Constructor which is passed a reference to the active object, the parameters for the method, and a reference to the future which contains the result.//(主动对象的引用,方法的参数的引用和Future对象)

logMsg_MO(Logger * logger, const char * msg,

ACE_Future &future_result);

virtual ~logMsg_MO();

//The call() method will be called by the Logger Active Object class, once this method object is dequeued from the activation queue. This is implemented so that it does two things. First it must execute the actual implementation method (which is specified in the Logger class. Second, it must set the result it obtains from that call in the future object that it has returned to the client.Note that the method object always keeps a reference to the same future object that it returned to the client so that it can set theresult value in it.

//1.执行在主动对象中实际编写的方法,2.设置返回值

virtual int call (void);

private:

Logger * logger_;

const char* msg_;

ACE_Future future_result_;

};

logMsg_MO.cpp==>向日志系统中写入文件

#pragma once

#include "LogMsgMo.h"

logMsg_MO::logMsg_MO(Logger * logger, const char * msg, ACE_Future &future_result):logger_(logger), msg_(msg),(future_result)

{

ACE_DEBUG((LM_DEBUG, "(%t) logMsg invoked \n"));

}

//Destructor

logMsg_MO::~logMsg_MO()

{

ACE_DEBUG ((LM_DEBUG, "(%t) logMsg object deleted.\n"));

}

//Invoke the logMsg() method

int logMsg_MO::call (void)

{

return this->future_result_.set (

this->logger_->logMsg_i (this->msg_));

}

Name_Mo.h==>获取线程的名称

#pragma once

#include "ace/Method_Object.h"

#include "ace/Future.h"

#include "Log.h"

class name_MO: public ACE_Method_Object

{

public:

//Constructor which is passed a reference to the active object, theparameters for the method, and a reference to the future which contains the result.

name_MO(Logger * logger, ACE_Future &future_result);

virtual ~name_MO();

//The call() method will be called by the Logger Active Object class, once this method object is dequeued from the activation queue. This is implemented so that it does two things. First it must execute the actual implementation method (which is specified in the Logger class. Second, it must set the result it obtains from that call in the future object that it has returned to the client.Note that the method object always keeps a reference to the same future object that it returned to the client so that it can set theresult value in it.

virtual int call (void);

private:

Logger * logger_;

ACE_Future future_result_;

};

Name_Mo.cpp==>获取线程的名称

#pragma once

#include "Name_Mo.h"

//Implementation for the name_MO method object.

//Constructor

name_MO::name_MO(Logger * logger, ACE_Future &future_result):

logger_(logger), future_result_(future_result)

{

ACE_DEBUG((LM_DEBUG, "(%t) name() invoked \n"));

}

//Destructor

name_MO::~name_MO()

{

ACE_DEBUG ((LM_DEBUG, "(%t) name object deleted.\n"));

}

//Invoke the name() method

int name_MO::call (void)

{

return this->future_result_.set (this->logger_->name_i ());

}

4.程序的运行结果

100111092703.png

1-4行主线程执行

5行Logger线程执行

6行主线程执行

7行Logger线程执行

8-15行主线程执行

16行主线程等待执行结果

17-32行Logger线程执行

33行主线程执行,获得返回结果!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《线性代数引论》是由Gilbert Strang编写的一本经典教材,是大多数线性代数课程的标准教材。该书从向量、矩阵和行列式的基础知识入手,涵盖了线性方程组、向量空间、线性变换、特征值以及矩阵分解和应用等内容。 在这本教材中,Strang强调了线性代数对于科学、工程、计算机科学和经济学等领域的重要性及其实际应用价值。他还提出了一些直观的方法和技巧,以帮助读者更好地理解线性代数的概念和应用。 此外,该书还包含了大量的例子和练习,以帮助读者更好地巩固所学知识。这些例子和练习涵盖了多个领域和应用,包括计算机图形学、信号处理和金融等。 总体而言,《线性代数引论》的第5版是一本优秀的线性代数教材,既适用于初学者,也适用于高级应用领域的专业学者。它提供了一种清晰、直观和深入的理解线性代数的方式,是现代科学和工程教育的经典参考书。 ### 回答2: 《线性代数导论》是一本由Gilbert Strang所著的教材,是关于线性代数基础概念与应用的全面介绍。 这本书第五版的最大特点,是它作者在保留传统线性代数教材的基础上,增加了部分对现代数学发展的最新见解。这使得这本书亦适合于进阶学习线性代数的读者的研究需求。 本书共计十二章,涉及的领域有:向量和矩阵、行列式、向量空间、线性变换、特征值与特征向量、正交性与证明、对称矩阵与二次型等多个方面。 书中对这些概念的介绍,始终保持着逐步深入、由浅入深的原则。作者使用矩阵的分块以及向量运算的独特方式,有助于读者更清晰、更简便地理解运用这些概念的具体方法。 《线性代数导论》提供了大量的练习题和解答,能够让读者逐渐熟悉概念的应用,掌握本书所讲述的知识。此外,书中还有一些关于基于线性代数的研究过程和发展的阅读材料,可以帮助读者更深入地理解和应用所学的知识。 总之,这本书对于希望系统地学习线性代数的读者而言,是一本非常值得推荐的经典教材。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值