/**************************************************************************** * Roller Coaster Simulation * * Title: roller_coaster.java, Kevin C. Rea, 1999 * **************************************************************************** * * Invariant:: 0 <= seats_available <= N
Ride() is the operation of getting in line and taking a ride on the coaster Load() is the operation of loading the passengers and giving the ride Unload() is the operation to unload the passengers when the ride is over N is how many seats the coaster has
Coarse-Grained Solution: Ride(): <await 0 < seats_available && <= N ==> --seats_available> {coaster_loading_passengers == TRUE}
Load(): <await seats_available == 0 ==> seats_available += N> {passengers_riding > 0}
Unload(): <--passengers_riding>
Ensuring the Invariant: (passengers_waiting > 0 ==> seats_available == 0 || coaster_loading_passengers || passengers_riding > 0) && Exclusion:: (passengers_riding > 0 ==> !coaster_loading_passengers) && (coaster_loading_passengers ==> passengers_riding == 0) && (0 <= seats_available <= N)
*/
import Utilities.*; import Synchronization.*;
/* Main Driver */ class roller_coaster extends MyObject {
public static int M = 25; // Number of people in park public static int P = 1; // Number of passenger cars public static int N = 4; // Number of passengers a car holds public static void main(String[] args) { Monitor rcMon = new Monitor();
/* Create the Objects */ car theCar; passenger aPassenger;
/* Create arrays of threads for initialization */ Thread t1[] = new Thread[M]; Thread t2[] = new Thread[P];
/* Fill the thread arrays */ for (int i = 0; i < M; i++) { aPassenger = new passenger(i, rcMon); t1[i] = new Thread(aPassenger); }
for (int i = 0; i < P; i++) { theCar = new car(i, rcMon); t2[i] = new Thread(theCar); }
/* Start Threads */ for(int i = 0; i < M; i++) { t1[i].start(); }
/* Start Threads */ for(int i = 0; i < P; i++) { t2[0].start(); }
try { for (int i = 0; i < M; i++) { t1[i].join(); } } catch (InterruptedException e) { System.err.println("Interrupted out of passenger thread join"); }
try { for (int i = 0; i < P; i++) { t2[i].join(); } } catch (InterruptedException e) { System.err.println("Interrupted out of coaster thread join"); }
System.out.println("Program has terminated Normally");
} /* End Main */ } /* End coaster class */
////////////////////////////// PASSENGER CLASS ////////////////////////////// class passenger extends MyObject implements Runnable { private int id; private Monitor passengerMon;
public passenger(int i, Monitor monitorIn) { id = i; this.passengerMon = monitorIn; }
public void run() { while(true) { nap((int) random(80)); passengerMon.Ride(id); } } } // end passenger class
/////////////////////////////////// CAR CLASS ////////////////////////////// class car extends MyObject implements Runnable { private int id; private Monitor carMon;
public car(int i, Monitor monitorIn) { id = i; this.carMon = monitorIn; }
public void run() { while(true) { carMon.Load(id); nap((int) random(80)); carMon.Unload(id);
} } } // end car class
class Monitor { private int i, line_length; // Number of passengers waiting to board the car. private int seats_available = 0; boolean coaster_loading_passengers = false; boolean passengers_riding = true;
/* For each <awaitBĦ -> SĦ>, declare one private notification instance of class Object */ private Object notifyPassenger = new Object(); // enter/exit protocol provides mutual exclusion. private Object notifyCar = new Object(); // the car waits on this.
// For each <awaitBi -> Si> define one private synchronized method (checkBSi) public void Ride(int i) { synchronized (notifyPassenger) { while (!checkSeats()) { try { notifyPassenger.wait(); } catch (InterruptedException e){} } } System.out.println("Passenger "+ i + " gets in car at: " + System.currentTimeMillis()); synchronized (notifyCar) {notifyCar.notify();} }
// checkBSi private synchronized boolean checkSeats() { if ((seats_available > 0) && (seats_available <= roller_coaster.N) && (!passengers_riding)) { seats_available--; return true; } else return false; }
/* For each <awaitBĦ -> SĦ>, define one public (non-synchronized) methodĦ */ public void Load(int i) { synchronized (notifyCar) { while (!checkRiding()) { try { notifyCar.wait(); } catch (InterruptedException e){} } } System.out.println("The Car is full and gives RIDE at >> "+ System.currentTimeMillis()); synchronized(notifyPassenger) {notifyPassenger.notifyAll();} }
private synchronized boolean checkRiding() { if (seats_available == 0) { seats_available = roller_coaster.N; coaster_loading_passengers = true; passengers_riding = true; return true; } else return false; }
/* <Sj> */ public void Unload(int i) { synchronized (this) { passengers_riding = false; coaster_loading_passengers = false; } System.out.println("The Car RETURNS and unloads passengers at >> "+ System.currentTimeMillis()); synchronized(notifyPassenger) {notifyPassenger.notifyAll();} } } // end roller_coaster monitor class
/*
Java version=1.2.1, Java vendor=Sun Microsystems Inc. OS name=Windows NT, OS arch=x86, OS version=4.0 Sat Aug 28 15:34:19 EDT 1999 The Car is full and gives RIDE at >> 935868859630 The Car RETURNS and unloads passengers at >> 935868859740 Passenger 23 gets in car at: 935868859740 Passenger 15 gets in car at: 935868859740 Passenger 8 gets in car at: 935868859740 Passenger 1 gets in car at: 935868859740 The Car is full and gives RIDE at >> 935868859750 The Car RETURNS and unloads passengers at >> 935868859780 Passenger 12 gets in car at: 935868859780 Passenger 21 gets in car at: 935868859790 Passenger 7 gets in car at: 935868859790 Passenger 4 gets in car at: 935868859800 The Car is full and gives RIDE at >> 935868859800 The Car RETURNS and unloads passengers at >> 935868859830 Passenger 6 gets in car at: 935868859830 Passenger 17 gets in car at: 935868859830 Passenger 20 gets in car at: 935868859830 Passenger 3 gets in car at: 935868859840 The Car is full and gives RIDE at >> 935868859840 The Car RETURNS and unloads passengers at >> 935868859910 Passenger 2 gets in car at: 935868859910 Passenger 0 gets in car at: 935868859910 Passenger 10 gets in car at: 935868859910 Passenger 16 gets in car at: 935868859910 The Car is full and gives RIDE at >> 935868859910 The Car RETURNS and unloads passengers at >> 935868859980 Passenger 1 gets in car at: 935868859990 Passenger 4 gets in car at: 935868859990 Passenger 6 gets in car at: 935868859990 The Car is full and gives RIDE at >> 935868859990 Passenger 5 gets in car at: 935868859990 The Car RETURNS and unloads passengers at >> 935868860061 Passenger 17 gets in car at: 935868860061 Passenger 3 gets in car at: 935868860071 Passenger 7 gets in car at: 935868860071 Passenger 12 gets in car at: 935868860071 The Car is full and gives RIDE at >> 935868860071 .....
*/ // end ouput run (compiled with Java 1.2.1 Native Threads)