Selathco 0.91 generated HTML
Predchozi Table of contents ) Dalsi

6. Programmer's Cookbook

Despite all theoretical information presented in previous chapters, the user may still be confused and not able to use J-Sim at all. This chapter should help him by giving him practical information on how to build up a simulation program efficiently in the shortest possible time.

6.1. Creating a Simulation

The simulation is usually created in the main() method of a class founded especially for this purpose. Please note that there is no need to inherit a new subclass of JSimSimulation, this class can be used directly. Start with a file called Example.java. In its main() method, we will create a simulation named "First simulation". Because some processes are to be added and activated in the future, all exceptions that could possibly be thrown out must be caught. The best way how to do it is to write just one exception handler at the end of the main() method, catching all instances of JSimException and its subclasses. In its corresponding finally block, the user must shut down the simulation. If the user forgets to do it, the program will hang up upon termination since there will be some suspended threads. Note that the class must be named Example to have the name identical with the name of the file (without the extension, of course). Also, all necessary classes from the J-Sim package must be imported.


import cz.zcu.fav.kiv.jsim.*;
public class Example
{
 public static void main(String[] args)
 {
  JSimSimulation        simulation = null;
  try
  {
   simulation = new JSimSimulation("First simulation");
   // Some code will be inserted here:
   // ......................
  } // try
  catch (JSimException e)
  {
   e.printStackTrace();
   e.printComment(System.err);
  } // catch
  finally
  {
   simulation.shutdown();
  }
 } // main
} // Example

Trying to compile this file now (javac Example.java) will result in an error saying that JSimException is never thrown in the body of the try block. This is just a preparation of the source code for further improvement, please wait with the compilation until some processes are added into the simulation.

6.2. Creating a Process

Several necessary steps must be done in order to create a process:

  1. A new class must be founded, extending the class JSimProcess. This class can be in its own separate file (and then it must be marked as public) or in the file where the main program is placed (Example.java). Then it must not be marked as public. Example (file MyProcess.java):
    
    public class MyProcess extends JSimProcess
    { // .....
    } // class MyProcess
    
    

  2. The new class must have a constructor, invoking JSimProcess' constructor as its first command. This is due to the fact that JSimProcess has no constructor without parameters and therefore, this constructor cannot be invoked implicitly. Because JSimProcess' constructor requires two parameters (a name and a reference to a simulation), it is good to have these two values as parameters of the new constructor, too. JSimProcess' constructor throws out three exceptions:

    • JSimSimulationAlreadyTerminatedException;

    • JSimInvalidParametersException;

    • JSimTooManyProcessesException.
    It makes no sense to catch them inside the new constructor; therefore, they should be listed in the throws clause. Some new parameters can be added to constructor's header, as well as new code to its body. Example (still file MyProcess.java):
    
    public MyProcess(String name, JSimSimulation sim,
                     ... new parameters ...)
         throws JSimSimulationAlreadyTerminatedException,
                JSimInvalidParametersException,
                JSimTooManyProcessesException
    {
     super(name, sim);
     // ..... new code
    } // constructor
    
    

  3. The life() method of the new process must be overwritten. There are no special constraints or recommendations about that. Example (still file MyProcess.java):
    
    protected void life()
    {
     message("Hello!");
    } // life
    
    

  4. A new instance of MyProcess must be created in the main program after the point where the simulation is created. It will be automatically added to the simulation. Example (file Example.java):
    
    public static void main(String[] args)
    {
     JSimSimulation  simulation = null;
     MyProcess       process = null;
    
     try
     {
      simulation = new JSimSimulation("First simulation");
      process = new MyProcess("My process No 1",
                              simulation,
                              ... other parameters ...);
     } // try
     catch (JSimException e)
     {
      e.printStackTrace();
      e.printComment(System.err);
     } // catch
     finally
     {
      simulation.shutdown();
     }
    } // main
    
    
    
    

Now, compile both files and run the example:

  1. javac MyProcess.java

  2. javac Example.java

  3. java Example (1)

Now, it is possible to compile both files without errors, however, when the example is run, nothing happens. This is due to the fact that the process was not activated and the simulation was not asked to run.

6.3. Running the Simulation

When a process is created, it should be activated. A process can be activated by the main program or by another process. However, if there is just one process within the simulation, or no process has been activated yet, the latter case is not possible. A process will be activated at a certain time when its activate() method is called with the required time as parameter. Example (file Example.java):


process = new MyProcess("My process No 1",
                        simulation,
                        ... other parameters ...);
process.activate(1.2345);

Once a process is activated, it is able to care about its own scheduling using the hold() method; therefore, no other activation is needed.

Now, attention should be turned to the simulation and its execution. Every simulation can be principally executed in two ways: a pre-programmed way and an interactive way when the simulation's execution is driven by the user. The second one will be explained as first, thanks to its enormous ease. After the point where processes are activated, a call to the simulation's runGUI() method must be inserted. The method will switch the simulation to the graphics mode and will wait until the user presses the "Quit" button. Example (file Example.java):


simulation = new JSimSimulation("First simulation");
process = new MyProcess("My process No 1",
                        simulation,
                        ... other parameters ...);
process.activate(1.2345);
simulation.runGUI();

The second possibility is based on calls to the step() method. Usually, it is done in a while or for cycle as shown here:

while (simulation.step() == true)
 ;

The step() method returns true if the simulation is not terminated, i.e. it can do another step. This is a potentially dangerous construction since the simulation can contain an infinite process. Such a process will make the simulation infinite too; therefore, the step() method will never return false and the program will never finish. There are two ways how to avoid this. Limit the execution either by time or by a number of steps to be executed.

The time limitation can be realized in the way shown below, using the simulation's method getCurrentTime():


while ((simulation.getCurrentTime() < 100.0)
      && (simulation.step() == true))
 ;

The second way of limitation is usually realized by a for cycle which has a counter of steps executed:

for (int i = 0; (i < 25) && (simulation.step() == true); i++)
 ;

In both cases, if the simulation terminates before the condition is fulfilled, other steps are not required to be executed.

6.4. Influencing Other Processes

J-Sim provides two methods in class JSimProcess allowing processes to influence other processes present in the system: cancel() and activate(). The first one deletes all process' events from the calendar, the second one adds a new event to the calendar.

In order to influence another process, a process needs a reference to it. Since processes have no access to other processes during their life, they must obtain this reference upon their creation and store it into a variable. That is shown in the following example (file MyProcess.java):


public class MyProcess extends JSimProcess
{
 public JSimProcess anotherProcess;

 public MyProcess(String name, JSimSimulation sim,
                  JSimProcess another)
     throws JSimSimulationAlreadyTerminatedException,
            JSimInvalidParametersException,
            JSimTooManyProcessesException
 {
  super(name, sim);
  anotherProcess = another;
 } // constructor

 protected void life()
 {
  // .....
  anotherProcess.cancel();
  // .....
  anotherProcess.activate(time);
  // .....
 } // life
} // class MyProcess

Then, the process can influence another process' scheduling. However, sometimes more than one process needs to be influenced. One possible solution is to pass as many processes as needed to the constructor, for example as an array. Another solution is to add a method to the influencing process that other processes will use to set the process to be influenced. In this case, processes using the method must have a reference to the influencing process in order to be able to invoke the method. This can be arranged in the simple way described above - one parameter in the constructor. Also note that the method can be invoked from outside only when the influencing process is passive, i.e. another process (which calls the method) is active. Therefore, only one process can be influenced during one step. A simple example is shown below:

public class MyProcess extends JSimProcess
{
 public JSimProcess anotherProcess;

 // No changes in constructor
 // No changes in life()

 public void setAnother(JSimProcess another)
 {
  anotherProcess = another;
 } // setAnother
} // class MyProcess

6.5. Working with Queues

Before any queue can be created and used, a simulation must exist which will be used as a parameter of queue's constructor. All this is usually done in the main program but not necessarily. An example follows (file Example.java):


public static void main(String[] args)
{
 JSimSimulation        sim = null;
 JSimHead              queue = null;
 try
 {
  sim = new JSimSimulation("Simulation with queues");
  queue = new JSimHead("Little queue", sim);
  // ... other code
} // main

As soon as the queue is created, some elements can be inserted into it. When creating them, the data they hold are passed to them as the only parameter of their constructor. In the following example, five integer numbers will be inserted into the queue already created in previous example:

// .....
JSimLink  element;
int       i;
// .....
for (i = 0; i < 5; i++)
{
 element = new JSimLink(new Integer(i));
 element.into(queue);
} // for

Of course, the user is not limited to integer values only. Instances of any class can be inserted into the queue, for example floating-point numbers. In the following example, two floating-point numbers are inserted into the queue, one just after the first element and one just before the last one, using JSimLink's methods follow() and precede():

// .....
JSimLink  before, after;
// .....
after  = new JSimLink(new Float(0.5));
before = new JSimLink(new Float(3.5));
after.follow(queue.first());
before.precede(queue.last());

To retrieve the data back and to print it, the user must distinguish between objects of different data types. Every element's data type can be obtained using its getDataType() method. Then, the user can decide whether to retype the data obtained from getData() to Integer or to Float. The following example prints out all data present in the queue, removing them from the queue as soon as they are printed out. To remove an element from the queue, its out() method is called. Since there are not usually any other reference to the element, it is disposed automatically by JVM. After each removal, the number of elements left in the queue is printed out.

// .....
String    dataType;
Integer   intObject;
Float     floatObject;
// .....
while (!queue.empty())
{
 element = queue.first();
 dataType = element.getDataType();
 System.out.println("The first element is of type: "
                    + dataType);
 switch (dataType.charAt(dataType.lastIndexOf('.') + 1))
 {
  case 'I': // Integer
   intObject = (Integer) element.getData();
   System.out.println("Data: " + intObject.toString());
   break;
  case 'F': // Float
   floatObject = (Float) element.getData();
   System.out.println("Data: " + floatObject.toString());
   break;
  default:
   System.out.println("There is an unknown object at"
                       + " the head of the queue.");
 } // switch
 element.out();
 System.out.println("Number of items in the queue: "
                    + queue.cardinal());
} // while


  • (1) Without any extension!

Predchozi
Converted by Selathco 0.91 on 01.09.2001 18:44
Dalsi