⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 agent.java

📁 java实现的P2P多agent中间件
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
			// first element
			if((o2aQueueSize != 0) && (o2aQueue.size() == o2aQueueSize))
				o2aQueue.remove(0);

			o2aQueue.add(o);

			// If we are going to block, then activate behaviours after storing the CondVar object
			if(blocking) {
				cond = new CondVar();

				// Store lock for later, when getO2AObject will be called
				o2aLocks.put(o, cond);
			}
		} // end synchronization
		// Reactivate the O2AManager if any or the whole agent if no O2AManager is set. 
		if (o2aManager == null){
			// This method is synchronized on the scheduler
			activateAllBehaviours();
		} else {
			o2aManager.restart();
		}
		if (blocking)
			// Sleep on the condition. This method is synchronized on the condvar
			cond.waitOn();
	}

	/**
	 This method picks an object (if present) from the internal
	 object-to-agent communication queue. In order for this method to
	 work, the agent must have declared its will to accept objects
	 from other software components running within its JVM. This can
	 be achieved by calling the
	 <code>jade.core.Agent.setEnabledO2ACommunication()</code> method.
	 If the retrieved object was originally inserted by an external
	 component using a blocking call, that call will return during the
	 execution of this method.
	 <br>
	 <b>NOT available in MIDP</b>
	 <br>
	 @return the first object in the queue, or <code>null</code> if
	 the queue is empty.
	 @see jade.wrapper.AgentController#putO2AObject(Object o, boolean blocking)
	 @see jade.core.Agent#setEnabledO2ACommunication(boolean enabled, int queueSize)
	 */
	public Object getO2AObject() {

		// Return 'null' if object-to-agent communication is disabled
		if(o2aQueue == null)
			return null;

		CondVar cond = null;
		Object result = null;
		synchronized (o2aQueue) {
			if(o2aQueue.isEmpty())
				return null;

			// Retrieve the first object from the object-to-agent
			// communication queue
			result = o2aQueue.remove(0);

			// If some thread issued a blocking putO2AObject() call with this
			// object, wake it up. cond.set is synchronized on CondVar object
			cond = (CondVar)o2aLocks.remove(result);
		}

		if(cond != null) {
			cond.set();
		}

		return result;

	}


	/**
	 This method declares this agent attitude towards object-to-agent
	 communication, that is, whether the agent accepts to communicate
	 with other non-JADE components living within the same JVM.
	 <br>
	 <b>NOT available in MIDP</b>
	 <br>
	 @param enabled Tells whether Java objects inserted with
	 <code>putO2AObject()</code> will be accepted.
	 @param queueSize If the object-to-agent communication is enabled,
	 this parameter specifiies the maximum number of Java objects that
	 will be queued. If the passed value is 0, no maximum limit is set
	 up for the queue.

	 @see jade.wrapper.AgentController#putO2AObject(Object o, boolean blocking)
	 @see getO2AObject()

	 */
	public void setEnabledO2ACommunication(boolean enabled, int queueSize) {
		if(enabled) {
			if(o2aQueue == null)
				o2aQueue = new ArrayList(queueSize);

			// Ignore a negative value
			if(queueSize >= 0)
				o2aQueueSize = queueSize;
		}
		else {

			// Wake up all threads blocked in putO2AObject() calls
			Iterator it = o2aLocks.values().iterator();
			while(it.hasNext()) {
				CondVar cv = (CondVar)it.next();
				if (cv != null) cv.set();
			}

			o2aQueue = null;
		}

	}
	
	/**
	 * Sets the behaviour responsible for managing objects passed to the agent by
	 * means of the Object-To-Agent (O2A) communication mechanism.
	 * If the O2A manager behaviour is set, whenever an object is inserted in the
	 * O2A queue by means of the <code>putO2AObject()</code> method, only the manager 
	 * is waken up. This improves the efficiency since all behaviours not interested in 
	 * O2A communication remain sleeping.  
	 <br>
	 <b>NOT available in MIDP</b>
	 <br>
	 * @param b The behaviour that will act as O2A manager.
	 * 
	 * @see jade.wrapper.AgentController#putO2AObject(Object o, boolean blocking)
	 * @see getO2AObject()
	 */
	public void setO2AManager(Behaviour b) {
		o2aManager = b;
	}
	//#MIDP_EXCLUDE_END


	//#APIDOC_EXCLUDE_BEGIN

	/**
	 This method is the main body of every agent. It 
	 provides startup and cleanup hooks for application 
	 programmers to put their specific code into.
	 @see jade.core.Agent#setup()
	 @see jade.core.Agent#takeDown()
	 */
	public final void run() {
		try {
			myLifeCycle.init();
			while (myLifeCycle.alive()) {
				try {
					myLifeCycle.execute();
					// Let other agents go on
					Thread.yield();
				}
				catch (JADESecurityException jse) {
					// FIXME: maybe we should send a message to the agent
					System.out.println("JADESecurityException: "+jse.getMessage());
				}
				catch (InterruptedException ie) {
					// Change LC state request from the outside. Just do nothing
					// and let the new LC state do its job
				}
				catch (InterruptedIOException ie) {
					// Change LC state request from the outside. Just do nothing
					// and let the new LC state do its job
				}
				catch (Interrupted i) {
					// Change LC state request from the outside. Just do nothing
					// and let the new LC state do its job
				}
			}
		}
		catch(Throwable t) {
			System.err.println("***  Uncaught Exception for agent " + myName + "  ***");
			t.printStackTrace();
		}
		terminating = true;
		myLifeCycle.end();
	}		
	//#APIDOC_EXCLUDE_END



	/**
	 Inner class ActiveLifeCycle
	 */
	private class ActiveLifeCycle extends LifeCycle {
		private static final long serialVersionUID = 11111;
		private ActiveLifeCycle() {
			super(AP_INITIATED);
		}

		public void setState(int s) {
			myState = s;
		}

		public void init() {
			setActiveState(AP_ACTIVE);
			//#MIDP_EXCLUDE_BEGIN
			notifyStarted();
			//#MIDP_EXCLUDE_END
			setup();
			restarting = false;
		}

		public void execute() throws JADESecurityException, InterruptedException, InterruptedIOException {
			// Select the next behaviour to execute
			Behaviour currentBehaviour = myScheduler.schedule();
			// Remember how many messages arrived
			int oldMsgCounter = messageCounter;

			// Just do it!
			currentBehaviour.actionWrapper();

			// If the current Behaviour has blocked and more messages arrived
			// in the meanwhile, restart the behaviour to give it another chance
			if((oldMsgCounter != messageCounter) && (!currentBehaviour.isRunnable())) {
				currentBehaviour.restart();
			}

			// When it is needed no more, delete it from the behaviours queue
			if(currentBehaviour.done()) {
				currentBehaviour.onEnd();
				myScheduler.remove(currentBehaviour);
				currentBehaviour = null;
			}
			else {
				synchronized(myScheduler) {
					// Need synchronized block (Crais Sayers, HP): What if
					// 1) it checks to see if its runnable, sees its not,
					//    so it begins to enter the body of the if clause
					// 2) meanwhile, in another thread, a message arrives, so
					//    the behaviour is restarted and moved to the ready list.
					// 3) now back in the first thread, the agent executes the
					//    body of the if clause and, by calling block(), moves
					//   the behaviour back to the blocked list.
					if(!currentBehaviour.isRunnable()) {
						// Remove blocked behaviour from ready behaviours queue
						// and put it in blocked behaviours queue
						myScheduler.block(currentBehaviour);
						currentBehaviour = null;
					}
				}
			}
		}

		public void end() {
			clean(false);
		}

		public boolean transitionTo(LifeCycle to) {
			// We can go to whatever state unless we are terminating
			if (!terminating) {
				// The agent is going to leave this state. When 
				// the agent will enter this state again it must be 
				// in AP_ACTIVE
				myState = AP_ACTIVE;
				return true;
			}
			else {
				return false;
			}
		}

		public void transitionFrom(LifeCycle from) {
			activateAllBehaviours();
		}

		public boolean isMessageAware() {
			return true;
		}
	} // END of inner class ActiveLifeCycle


	/**
	 Inner class DeletedLifeCycle
	 */
	private class DeletedLifeCycle extends LifeCycle {
		private static final long serialVersionUID = 11112;
		private DeletedLifeCycle() {
			super(AP_DELETED);
		}

		public void end() {
			clean(true);
		}

		public boolean alive() {
			return false;
		}		
	} // END of inner class DeletedLifeCycle

	//#MIDP_EXCLUDE_BEGIN
	/**
	 Inner class SuspendedLifeCycle
	 */
	private class SuspendedLifeCycle extends LifeCycle {
		private static final long serialVersionUID = 11113;
		private SuspendedLifeCycle() {
			super(AP_SUSPENDED);
		}

		public void execute() throws JADESecurityException, InterruptedException, InterruptedIOException {
			waitUntilActivate();
		}

		public void end() {
			clean(false);
		}

		public boolean transitionTo(LifeCycle to) {
			// We can only die or resume
			return (to.getState() == AP_ACTIVE || to.getState() == AP_DELETED); 
		}		
	} // END of inner class SuspendedLifeCycle

	//#MIDP_EXCLUDE_END


	//#APIDOC_EXCLUDE_BEGIN
	public void clean(boolean ok) {
		if (!ok) {
			System.out.println("ERROR: Agent " + myName + " died without being properly terminated !!!");
			System.out.println("State was " + myLifeCycle.getState());
		}
		//#MIDP_EXCLUDE_BEGIN
		// Reset the interrupted state of the Agent Thread
		Thread.interrupted();
		//#MIDP_EXCLUDE_END

		myBufferedLifeCycle = myLifeCycle;
		myLifeCycle = myActiveLifeCycle;
		takeDown();
		pendingTimers.clear();
		myToolkit.handleEnd(myAID);
		myLifeCycle = myBufferedLifeCycle;
	}
	//#APIDOC_EXCLUDE_END

	/**
	 This protected method is an empty placeholder for application
	 specific startup code. Agent developers can override it to
	 provide necessary behaviour. When this method is called the agent
	 has been already registered with the Agent Platform <b>AMS</b>
	 and is able to send and receive messages. However, the agent
	 execution model is still sequential and no behaviour scheduling
	 is active yet.

	 This method can be used for ordinary startup tasks such as
	 <b>DF</b> registration, but is essential to add at least a
	 <code>Behaviour</code> object to the agent, in order for it to be
	 able to do anything.
	 @see jade.core.Agent#addBehaviour(Behaviour b)
	 @see jade.core.behaviours.Behaviour
	 */
	protected void setup() {}

	/**
	 This protected method is an empty placeholder for application
	 specific cleanup code. Agent developers can override it to
	 provide necessary behaviour. When this method is called the agent
	 has not deregistered itself with the Agent Platform <b>AMS</b>
	 and is still able to exchange messages with other
	 agents. However, no behaviour scheduling is active anymore and
	 the Agent Platform Life Cycle state is already set to
	 <em>deleted</em>.

	 This method can be used for ordinary cleanup tasks such as
	 <b>DF</b> deregistration, but explicit removal of all agent
	 behaviours is not needed.
	 */
	protected void takeDown() {}

	//#MIDP_EXCLUDE_BEGIN
	/**
	 * This empty placeholder shall be overridden by user defined agents 
	 * to execute some actions before the original agent instance on the 
	 * source container is stopped (e.g. releasing local resources such 
	 * as a GUI).<br>
	 * <b>IMPORTANT:</b> At this point, it is ensured that the move process
	 * is successful and that a moved agent instance has been created on the 
	 * destination container 
	 * Therefore setting the value of a class field in this method will have
	 * no impact on the moved agent instance. Such parameters must indeed be 
	 * set <b>before</b> the <code>doMove()</code> method is called.
	 <br>
	 <b>NOT available in MIDP</b>
	 <br>
	 */
	protected void beforeMove() {}

	/**
	 Actions to perform after moving. This empty placeholder method can be
	 overridden by user defined agents to execute some actions just after
	 arriving to the destination agent container for a migration.
	 <br>
	 <b>NOT available in MIDP</b>
	 <br>
	 */
	protected void afterMove() {}

	/**
	 * This empty placeholder method shall be overridden by user defined agents 
	 * to execute some actions before copying an agent to another agent container.
	 * <br>
	 * <b>NOT available in MIDP</b>
	 * <br>
	 * @see beforeMove()
	 * @see afterClone()
	 */
	protected void beforeClone() {}

	/**
	 Actions to perform after cloning. This empty placeholder method can be
	 overridden by user defined agents to execute some actions just after
	 creating an agent copy to the destination agent container.
	 <br>
	 <b>NOT available in MIDP</b>
	 <br>
	 */
	protected void afterClone() {}
	//#MIDP_EXCLUDE_END

	// This method is used by the Agent Container to fire up a new agent for the first time
	// Mutual exclusion with itself and Agent.addPlatformAddress()
	synchronized void powerUp(AID id, Thread t) {
		if (myThread == null) {
			// Set this agent's name and address and start its embedded thread
			myName = id.getLocalName();
			myHap = id.getHap();

			myAID = id;
			myToolkit.setPlatformAddresses(myAID);

			myThread = t;
			myThread.start();
		}
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -