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

📄 threadedbehaviourfactory.java

📁 java实现的P2P多agent中间件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************
 JADE - Java Agent DEvelopment Framework is a framework to develop
 multi-agent systems in compliance with the FIPA specifications.
 Copyright (C) 2000 CSELT S.p.A. 
 
 GNU Lesser General Public License
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation, 
 version 2.1 of the License. 
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the
 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA  02111-1307, USA.
 *****************************************************************/

package jade.core.behaviours;

//#MIDP_EXCLUDE_FILE

import jade.core.Agent;
import jade.core.NotFoundException;

import java.util.Vector;
import java.util.Enumeration;

/**
 This class provides support for executing JADE Behaviours 
 in dedicated Java Threads. In order to do that it is sufficient 
 to add to an agent a normal JADE Behaviour "wrapped" into 
 a "threaded behaviour" as returned by the <code>wrap()</code> method
 of this class (see the example below).
 
 <pr><hr><blockquote><pre>
 ThreadedBehaviourFactory tbf = new ThreadedBehaviourFactory();
 Behaviour b = // create a JADE behaviour
 addBehaviour(tbf.wrap(b));
 </pre></blockquote><hr>
 
 This class also provides methods to control the termination of 
 the threads dedicated to the execution of wrapped behaviours
 
 <br>
 <b>NOT available in MIDP</b>
 <br>
 
 @author Giovanni Caire - TILAB
 */
public class ThreadedBehaviourFactory {
	// Thread states (only for debugging purpose)
	private static final String CREATED_STATE = "CREATED";
	private static final String RUNNING_STATE = "RUNNING";
	private static final String CHECKING_STATE = "CHECKING";
	private static final String BLOCKED_STATE = "BLOCKED";
	private static final String SUSPENDED_STATE = "SUSPENDED";
	private static final String TERMINATED_STATE = "TERMINATED";
	private static final String INTERRUPTED_STATE = "INTERRUPTED";
	private static final String ERROR_STATE = "ERROR";
	
	private Vector threadedBehaviours = new Vector();
	
	/**
	 * Wraps a normal JADE Behaviour <code>b</code> into a "threaded behaviour". Adding the 
	 * wrapper behaviour to an agent results in executing <code>b</code> in a dedicated Java Therad.
	 */
	public Behaviour wrap(Behaviour b) {
		return new ThreadedBehaviourWrapper(b);
	}
	
	/**
	 * @return The number of active threads dedicated to the execution of 
	 * wrapped behaviours.
	 */
	public int size() {
		return threadedBehaviours.size();
	}
	
	/**
	 * Interrupt all threaded behaviours managed by this ThreadedBehaviourFactory
	 */
	public void interrupt() {
		ThreadedBehaviourWrapper[] tt = getWrappers();
		for (int i = 0; i < tt.length; ++i) {
			tt[i].interrupt();
		}
	}
	
	/**
	 * Blocks until all threads dedicated to the execution of threaded 
	 * behaviours complete.
	 * @param timeout The maximum timeout to wait for threaded behaviour
	 * termination.
	 * @return <code>true</code> if all threaded behaviour have actually
	 * completed, <code>false</code> otherwise.
	 */
	public synchronized boolean waitUntilEmpty(long timeout) {
		long time = System.currentTimeMillis();
		long deadline = time + timeout;
		try {
			while(!threadedBehaviours.isEmpty()) {
				if (timeout > 0 && time >= deadline) {
					// Timeout expired
					break;
				}
				wait(deadline - time);
				time = System.currentTimeMillis();
			}
		}
		catch (InterruptedException ie) {
			// Interrupted while waiting for threaded behaviour termination
		}
		return threadedBehaviours.isEmpty();  	
	}
	
	/**
	 * Interrupt a threaded behaviour. This method should be used to abort a threaded behaviour 
	 * instead of getThread().interrupt() because i) the latter may have no effect if called just after 
	 * the threaded behaviour suspended itself and ii) the threaded behaviour may be suspended
	 * and in this case its Thread is null.
	 * @return the Thread that was interrupted if any.
	 */
	public Thread interrupt(Behaviour b) throws NotFoundException {
		ThreadedBehaviourWrapper wrapper = getWrapper(b);
		if (wrapper != null) {
			return wrapper.interrupt();
		}
		else {
			throw new NotFoundException(b.getBehaviourName());
		}
	}

	/**
	 * Suspend a threaded behaviour. This method has only effect if called by the threaded behaviour
	 * itself and has the effect of releasing its dedicated Java Thread. This can later be restored 
	 * by means of the <code>resume()</code> method.
	 */
	public void suspend(Behaviour b) {
		ThreadedBehaviourWrapper wrapper = getWrapper(b);
		if (wrapper != null) {
			wrapper.suspend();
		}
	}
	
	/**
	 * Resume a threaded behaviour. Assign a new Java Thread to a threaded behaviour that is
	 * currently suspended.
	 */
	public void resume(Behaviour b) {
		ThreadedBehaviourWrapper wrapper = getWrapper(b);
		if (wrapper != null) {
			wrapper.resume();
		}
	}
	
	/**
	 @return the Thread dedicated to the execution of the Behaviour <code>b</code>
	 */
	public Thread getThread(Behaviour b) {
		ThreadedBehaviourWrapper tb = getWrapper(b);
		if (tb != null) {
			return tb.getThread();
		}
		return null;
	}
	
	//#APIDOC_EXCLUDE_BEGIN
	/**
	 * This method is declared public for debugging purpose only
	 * @return All the wrapper behaviours currently used by this ThreadedBehaviourFactory
	 */
	public ThreadedBehaviourWrapper[] getWrappers() {
		synchronized (threadedBehaviours) {
			ThreadedBehaviourWrapper[] wrappers = new ThreadedBehaviourWrapper[threadedBehaviours.size()];
			for (int i = 0; i < wrappers.length; ++i) {
				wrappers[i] = (ThreadedBehaviourWrapper) threadedBehaviours.elementAt(i);
			}
			return wrappers;
		}
	}
	
	private ThreadedBehaviourWrapper getWrapper(Behaviour b) {
		synchronized (threadedBehaviours) {
			Enumeration e = threadedBehaviours.elements();
			while (e.hasMoreElements()) {
				ThreadedBehaviourWrapper tb = (ThreadedBehaviourWrapper) e.nextElement();
				if (tb.getBehaviour().equals(b)) {
					return tb;
				}
			}
			return null;
		}
	}
	
	/**
	 * Inner class ThreadedBehaviourWrapper
	 * This class is declared public for debugging purpose only
	 */
	public class ThreadedBehaviourWrapper extends Behaviour implements Runnable {
		private Thread myThread;
		private Behaviour myBehaviour;
		private volatile boolean restarted = false;
		private boolean finished = false;
		private volatile boolean suspended = false;
		private int exitValue;
		// Only for debugging purpose
		private volatile String threadState = CREATED_STATE;
		
		private ThreadedBehaviourWrapper(Behaviour b) {
			super(b.myAgent);
			myBehaviour = b;
			myBehaviour.setParent(new DummyParentBehaviour(myAgent, this));
		}
		
		public void onStart() {
			// Be sure both the wrapped behaviour and its dummy parent are linked to the 
			// correct agent
			myBehaviour.setAgent(myAgent);
			myBehaviour.parent.setAgent(myAgent);
			
			start();
		}
		
		private void start() {
			// Start the dedicated thread
			myThread = new Thread(this);
			myThread.setName(myAgent.getLocalName()+"#"+myBehaviour.getBehaviourName());
			myThread.start();			
		}
		
		public void action() {
			if (!finished) {
				block();
			}
		}
		
		public boolean done() {
			return finished;
		}
		
		public int onEnd() {
			// This check only makes sense if the ThreadedBehaviourWrapper is a child
			// of a SerialBehaviour. In this case in fact the ThreadedBehaviourWrapper 
			// terminates, but the parent must remain blocked.
			if (!myBehaviour.isRunnable()) {
				block();
			}
			return exitValue;
		}
		
		/**
		 Propagate the parent to the wrapped behaviour. 
		 NOTE that the <code>parent</code> member variable of the wrapped behaviour
		 must point to the DummyParentBehaviour --> From the wrapped behaviour
		 accessing the actual parent must always be retrieved through the

⌨️ 快捷键说明

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