• Nenhum resultado encontrado

4.2 A plataforma JADE

4.2.3 Comportamentos de Agentes

As ações ou comportamentos que um agente desempenha dentro de um SMA são fundamentais para que o objetivo final do sistema seja alcançado. JADE contém comportamentos específicos para a maioria das tarefas comuns na programação de agentes, tais como envio e recebimento de mensagens, bem como para construção de tarefas mais complexas. No desenvolvimento orientado a agentes com JADE, o agente deve obrigatoriamente ser uma instância direta ou indireta da classe

Agent e implementar tarefas específicas escrevendo um ou mais comportamentos através das

subclasses de Behaviour, instanciando-as e adicionando-as ao agente.

A estrutura dos comportamentos de JADE é suportada por um escalonador, interno à superclasse

Agent e transparente para o desenvolvedor, que gerencia automaticamente o escalonamento desses

comportamentos usando a política de escalonamento Round-Robin não-preemptivo em todos os comportamentos disponíveis na fila de pronto [Bellifemine05]. Em outras palavras, um comportamento é executado por vez por um determinado tempo (quantum). Quando acaba esse tempo, o comportamento pode voltar para o fim da fila, caso não tenha acabado de executar sua tarefa. O fato de ser não-preemptivo significa dizer que não existe prioridade entre os comportamentos, ou seja, cada comportamento adicionado deve ir para o fim da fila e todos têm a mesma fatia de tempo.

Do ponto de vista de programação concorrente, um agente é um objeto ativo com uma thread de controle interna. JADE usa o modelo de uma thread por agente ao invés de uma thread por tarefa ou conversação, com o objetivo de manter um número pequeno de threads necessárias para executar a plataforma de agentes.

A classe Behaviour

Behaviour é uma classe abstrata de JADE disponível no pacote jade.core.behaviours e que pode ser

usada para modelar uma tarefa genérica do agente. Por ser abstrata é uma classe que possui alguns métodos implementados e outros não [Deitel03], desta forma, a classe Behaviour tem como finalidade prover a estrutura de comportamentos que podem ser implementados para execução de agentes em JADE.

Os dois métodos principais da classe Behaviour são abstratos: action() e done(). O método action() deve ser implementado para realizar as tarefas ou ações que serão desempenhadas pelo agente através deste comportamento. O método done () é usado para informar ao escalonador do agente se o comportamento foi terminado ou não. Ele retorna true caso o comportamento tenha terminado e assim

este é removido da fila de comportamentos, e retorna false caso o comportamento ainda não tenha terminado, fazendo com que o método action() seja novamente executado.

Diversos outros métodos estão disponíveis para classe Behaviour, dentre os quais podemos citar: ƒ onEnd(): é um método invocado apenas uma vez, após o comportamento ter sido encerrado; ƒ onStart(): é um método executado uma única vez também, mas antes do início da execução

do comportamento do agente;

ƒ void block(): é um método utilizado para bloquear o comportamento. É possível passar como parâmetro desse método um tempo de bloqueio em milisegundos;

ƒ void restart(): reinicia um comportamento bloqueado; ƒ void reset(): restaura o estado inicial do comportamento;

ƒ boolean isRunnable(): retorna se o comportamento está bloqueado ou não.

Figura 4.4: Hierarquia das classes de comportamentos em JADE derivadas de Behaviour

JADE possui várias classes de comportamentos prontas para uso pelo desenvolvedor adequando- as de acordo com a necessidade específica do agente. A Figura 4.4 apresenta a hierarquia de classes que derivam de Behaviour.

A classe ReceiverBehaviour implementa um comportamento próprio para recebimento de

mensagens ACL. Ela encapsula o método receive() como uma operação atômica, tendo o comportamento encerrado quando uma mensagem ACL é recebida. ReceiverBehaviour possui o método getMessage() que permite receber a mensagem que foi enviada para o agente.

SimpleBehaviour, por sua vez, é uma classe abstrata que deve ser utilizada para modelar

comportamentos que não pode ter sub-comportamentos. Isto é, modela comportamentos que são feitos para serem únicos, monolíticos, e que não podem ser interrompidos. Possui quatro classes herdadas disponibilizadas pelo JADE. São elas:

ƒ jade.core.behaviours.CyclicBehaviour: define um comportamento simples que deve ser executado sempre. É uma classe abstrata que pode ser herdada para criação de comportamentos cuja execução será contínua. Essa característica deste tipo de comportamento faz com que ele se repita como se estivesse em um loop infinito, porque o método done() herdado da super classe Behaviour, sempre retorna o valor falso para comportamentos cíclicos;

ƒ jade.core.behaviours.TickerBehaviour: representa comportamentos que precisam ser executados periodicamente para realizar tarefas específicas. TickerBehaviour é uma classe abstrata que implementa um comportamento cujo objetivo é executar periodicamente um pedaço de código definido pelo desenvolvedor em uma determinada freqüência de repetições. O método onTick() deve ser redefinido para incluir o trecho de código que representa as ações que devem ser executadas periodicamente. O intervalo entre uma repetição e outra deve ser passado em milisegundos no construtor da classe;

ƒ jade.core.behaviours.OneShotBehaviour: modela uma tarefa atômica. Essa classe abstrata pode ser herdada para a criação de comportamentos para tarefas simples que precisam ser executadas apenas uma única vez (seu método done() retorna true). Tem como classe filha a classe SenderBehaviour;

x jade.core.behaviours.SenderBehaviour: é um comportamento do tipo

OneShotBehaviour para envio de mensagens ACL. Essa classe encapsula o método send() como uma operação atômica. Seu funcionamento restringe-se a realizar o

comportamento de enviar determinada mensagem ACL e logo em seguida ser finalizado. A mensagem ACL a ser enviada é passada como parâmetro no construtor da classe;

ƒ jade.core.behaviours.WakerBehaviour: representa um comportamento simples que deve ser executado depois de determinado tempo expirado. Em outras palavras, é uma classe abstrata que uma tarefa “OneShot” que é executada apenas depois que determinado tempo é expirado. No caso, a tarefa é inserida no método handleElapsedTimeout() o qual é chamado sempre que o intervalo de tempo é transcorrido.

A classe CompositeBehaviour é uma classe abstrata para realizar a modelagem de

comportamentos que representam tarefas complexa, ou seja, tarefas que são compostas por outras tarefas. Ela controla internamente seus sub-comportamentos seus intervalos de execução de acordo com alguma política de escalonamento. CompositeBehaviour possui três classes filhas disponibilizadas por JADE, são elas:

ƒ jade.core.behaviours.FSMBehaviour: representa um comportamento composto que possui o escalonamento de seus sub-comportamentos de acordo com uma máquina de estados finitos (Finite State Machine) definida pelo desenvolvedor. Nessa estrutura, cada sub-comportamento representa um estado na máquina de estados finitos. Esta classe de comportamento possui métodos para registrar estados e transições que definem como será realizado o escalonamento desses sub-comportamentos. Um FSMBehaviour deve ser definido a partir dos seguintes passos:

1) Determinar um único comportamento como estado inicial, usando o

registerFirstState() e passando como parâmetros o comportamento e o nome do

estado;

2) Determinar um ou mais comportamentos como estados finais através do método

registerLastState();

3) Determinar um ou mais comportamentos como estados intermediários através do método registerState();

4) Determinar, para cada estado, as transições deste com os outros estados através do método registerTransition().

ƒ jade.core.behaviours.ParallelBehaviour: define um comportamento composto com escalonamento concorrente de sub-comportamentos. Sua finalização dá-se quando alguma condição com relação à execução de seus sub-comportamentos é atendida. Essas condições são definidas passando-se como parâmetro no construtor da classe ParallelBehaviour um valor inteiro ou uma das constantes: WHEN_ALL ou WHEN_ANY. O valor inteiro é utilizado para definir o número de sub-comportamentos finalizados que representa a condição para finalização do comportamento paralelo. As constantes, por sua vez, são empregadas para definir que todos os comportamentos ou algum dos comportamentos, respectivamente, precisam ser encerrados para que encerre a execução da instância de ParallelBehaviour; ƒ jade.core.behaviours.SequentialBehaviour: representa um comportamento composto com

escalonamento seqüencial de sub-comportamentos. Ou seja, os seus sub-comportamentos são executados numa ordem seqüencial e o comportamento que foi decomposto apenas pode ser encerrado quando todos os seus sub-comportamentos tiverem finalizado sua execução. Para adicionar sub-comportamentos a comportamentos compostos do tipo ParallelBehaviour e

SequentialBehaviour devemos chamar o método addSubBehaviour().

Devido ao modelo não-preemptivo de escolha de comportamentos dos agentes, os programadores de agentes devem evitar uso de “loops” infinitos e até executar atividades muito longas dentro do método action() de comportamentos. Isso porque enquanto o método action() de algum comportamento estiver sendo executado, nenhum outro comportamento deste mesmo agente poderá ser executado até que este método finalize sua execução. Não é possível, por exemplo, interromper um comportamento durante a execução de um action(), passar o controle para outros comportamentos e voltar para o comportamento original de local onde tinha sido interrompido [Bellifemine04].