In: Computer Science
The project will study the coordination of multiple threads using semaphores.
The design should consist of two things:
(1) a list of every semaphore, its purpose, and its initial value, and
(2) pseudocode for each function. Code Your code should be nicely formatted with plenty of comments. The code should be easy to read, properly indented, employ good naming standards, good structure, and should correctly implement the design. Your code should match your pseudocode.
Project Language/Platform
This project must target a Unix platform and execute properly on our cs1 or csgrads1 Linux server.
The project must be written in Java. Elevator Simulation In this project threads are used to simulate people using an elevator to reach their floor.
The threads to be used are as follows: Person:
1) 49 people are in line at the elevator at the beginning of the simulation (1 thread per person).
2) Each person begins at floor 1.
3) Each person randomly picks a floor from 2 to 10.
4) A person will wait for an elevator to arrive at floor 1.
5) A person will board the elevator only if there is room.
6) Once at the destination floor, the person exits the elevator.
Elevator:
1) There is 1 elevator (1 thread for the elevator).
2) The elevator can only hold 7 people.
3) The elevator begins on floor 1.
4) The elevator leaves after the 7th person enters.
Main
1) Creates all threads and joins all person threads.
2) When last person reaches their floor, the simulation ends.
Other rules:
1) Each activity of each thread should be printed with identification (e.g., person 1).
2) A thread may not use sleeping as a means of coordinating with other threads.
3) Busy waiting (polling) is not allowed.
4) Mutual exclusion should be kept to a minimum to allow the most concurrency.
5) The semaphore value may not obtained and used as a basis for program logic.
6) All activities of a thread should only be output by that thread. Sample output:
Your project’s output should match the wording of the sample output:
Elevator door opens at floor 1
Person 0 enters elevator to go to floor 5
Person 1 enters elevator to go to floor 2
Person 2 enters elevator to go to floor 8
Person 3 enters elevator to go to floor 4
Person 4 enters elevator to go to floor 6
Person 5 enters elevator to go to floor 7
Person 6 enters elevator to go to floor 2
Elevator door closes
Elevator door opens at floor 2
Person 1 leaves elevator
Person 6 leaves elevator
Elevator door closes
Elevator door opens at floor 4
Person 3 leaves elevator
Elevator door closes
Elevator door opens at floor 5
Person 0 leaves elevator
Elevator door closes
Elevator door opens at floor 6
Person 4 leaves elevator
Elevator door closes
Elevator door opens at floor 7
Person 5 leaves elevator
Elevator door closes
Elevator door opens at floor 8
Person 2 leaves elevator
Elevator door closes
Elevator door opens at floor 1
…
Simulation done
public class Person implements Runnable{
//possible actions
public static final int WAITING = 1;
public static final int TAKING_STAIRS = 2;
public static final int WORKING = 3;
public static final int WALKING_OUTSIDE = 4;
public static final int RIDING = 5;
public static final int GOING_NOWHERE = -1;
public static final int OUTSIDE = -1;
public static final int IN_ELEVATOR = 0;
private static Building building;
private int personID;
private int destination;
private int location; //anything greater than zero is a floor
number
private long activityTime;
private int activity;
private Elevator elevator;
private Floor floor;
private Thread activePerson;
private Logger log;
private volatile boolean keepRunning;
private PersonState state = new PersonState();
public static void setBuilding(Building theBuilding){
building = theBuilding;
}
public Person(int personID){
this.personID = personID;
}
public void setStopRunning(){
keepRunning = false;
}
public boolean getKeepRunning(){
return keepRunning;
}
public synchronized void attention(){
activePerson.interrupt();
}
public synchronized void elevatorArrived(Elevator elevator) {
this.elevator = elevator;
}
public PersonState getState() {
state.personNumber = personID;
state.activity = activity;
state.destination = destination;
state.location = location;
if(elevator != null)
state.elevatorNumber = elevator.getElevatorNumber();
return state;
}
public int getPersonNumber(){
return personID;
}
public void start(){
destination = GOING_NOWHERE;
activity = WALKING_OUTSIDE;
if(Simulator.debug) log = new Logger("Person" + personID);
keepRunning = true;
if(activePerson == null){
activePerson = new Thread(this);
//activePerson.setDaemon(true);
activePerson.setPriority(Thread.NORM_PRIORITY - 2);
activePerson.start();
}
}
public void run(){
while(keepRunning){
switch(activity){
case WALKING_OUTSIDE:
if(wantsToEnter()){
building.peopleOutside--;
setDestination();
floor = building.enterBuilding();
location = floor.getFloorNumber();
if(destination > location){ //go up
activity = WAITING;
setWaitTime();
floor.summonElevatorUp(this);
action();
}else{ // work on first floor
building.peopleWorking++;
activity = WORKING;
destination = GOING_NOWHERE;
setWorkingTime();
action();
}
}else{ // did not enter
destination = GOING_NOWHERE;
location = OUTSIDE;
activity = WALKING_OUTSIDE;
setWorkingTime();
action();
}
break;
case TAKING_STAIRS:
if(location == destination){
building.peopleTakingStairs--;
building.peopleWorking++;
activity = WORKING;
floor = building.getFloor(location);
destination = GOING_NOWHERE;
setWorkingTime();
action();
}else if(destination > location){
climbUp();
}else{
climbDown();
}
break;
case WAITING:
if(elevator != null){
enterElevator();
}else{ //elevator not here yet
if(wantsToTakeStairs()){
floor.stopWaiting(this);
building.peopleTakingStairs++;
activity = TAKING_STAIRS;
if(destination > location){
climbUp();
}else{
climbDown();
}
}else{//continue to wait
setWaitTime();
action();
}
}
break;
case WORKING:
if(location == 1){
if(wantsToLeave()){
building.peopleOutside++;
building.peopleWorking--;
destination = GOING_NOWHERE;
location = OUTSIDE;
activity = WALKING_OUTSIDE;
setWorkingTime();
action();
}else{ // stay in the building
setDestination();
if(destination > location){ //go up
building.peopleWorking--;
activity = WAITING;
setWaitTime();
floor.summonElevatorUp(this);
action();
}else{ // work on same floor
activity = WORKING;
destination = GOING_NOWHERE;
setWorkingTime();
action();
}
}
}else{ // not on first floor
setDestination();
if(destination > location){ //go up
building.peopleWorking--;
activity = WAITING;
setWaitTime();
floor.summonElevatorUp(this);
action();
}else if(destination < location){
building.peopleWorking--;
activity = WAITING;
setWaitTime();
floor.summonElevatorDown(this);
action();
}else{ // work on same floor
activity = WORKING;
destination = GOING_NOWHERE;
setWorkingTime();
action();
}
}
break;
case RIDING:
if(elevator.getCurrentFloorNumber() == destination){
leaveElevator();
}else
setWaitTime();
action();
break;
}
if(Simulator.debug) log.write(getState().toString());
}
if(log != null)log.close();
}
private boolean wantsToEnter(){
double i = (Math.random() *
1000);
if(Simulator.debug)
log.write("Person: " + personID + " Wants to enter: " + i);
if ( i < 600) return true; else
return false;
}
private boolean wantsToTakeStairs(){
double i = (Math.random() *
10000);
if(Simulator.debug)
log.write("Person: " + personID + " Wants to climb: " + i);
if ( i < 600) return true; else
return false;
//return true;
}
private void setDestination() {
destination = ((int) (1 +
((Math.random() * 10000) % (building.MAX_FLOORS ))));
if(Simulator.debug) log.write("Person: " + personID + " Setting
destination: " + destination);
}
private void setWaitTime() {
activityTime = 1000 * ((int) (1 +
((Math.random() * 100) % 4)));
if(Simulator.debug)
log.write("Person: " + personID + " Maxwait: " +
activityTime);
}
private void setWorkingTime() {
activityTime = 1000 * ((int) (1 +
((Math.random() * 100) % 6)));
if(Simulator.debug)
log.write("Person: " + personID + " Business: " +
activityTime);
}
private boolean wantsToLeave() {
double i = (Math.random() *
10000);
if(Simulator.debug)
log.write("Person: " + personID + " Leaving number (6600): " +
i);
if ( i < 6600) return true; else
return false;
}
private void action(){
//if(Simulator.debug) log.write("About to sleep for " +
activityTime + " " + getState());
try{
activePerson.sleep(activityTime);
}catch(InterruptedException ix){
//intentionally left empty
}
}
private void climbUp(){
if(location != Building.MAX_FLOORS){
action();
++location;
}
}
private void climbDown(){
if(location != 1){
action();
--location;
}
}
private void enterElevator(){
try{
elevator.enterElevator(this);
//we don't get here unless we entered the elevator
elevator.setDestination(destination);
floor.stopWaiting(this);
floor = null;
location = IN_ELEVATOR;
activity = RIDING;
activityTime = Elevator.FLOOR_TRAVEL_TIME * Math.abs(location -
destination);
action();
}catch(ElevatorFullException fx){
resetWaitForElevator();
}catch(DoorClosedException cx){
try{
elevator.requestOpenDoor();//use loop so not reenterant
method
}catch(ElevatorMovingException mx){
resetWaitForElevator(); // assume the elevator has moved on
}
}
}
private void leaveElevator(){
try{
elevator.leaveElevator(this);
floor = building.getFloor(destination);
location = destination;
destination = GOING_NOWHERE;
activity = WORKING;
building.peopleWorking++;
setWorkingTime();
action();
}catch(DoorClosedException dx){
try{
elevator.requestOpenDoor();
}catch(ElevatorMovingException mx){
// missed our floor or not arrived yet either way push the
button
elevator.setDestination(destination);
}
}
}
private void resetWaitForElevator(){
if(Simulator.debug) log.write("Person " + personID + " missed
elevator " + elevator.getElevatorNumber());
floor.stopWaiting(this);
elevator = null;
setWaitTime();
action();
if(destination > location)
floor.summonElevatorUp(this);
else
floor.summonElevatorDown(this);
}
} // end Person
import java.util.*;
public class Elevator implements Runnable {
//Direction for motionDirection
public static final int MOVING_UP = 1;
public static final int NO_DIRECTION = 0;
public static final int MOVING_DOWN = -1;
//state values for motionState
public static final int MOVING = 1;
public static final int STOPPED = 0;
//state values for door
public static final int DOOR_OPEN = 1;
public static final int DOOR_CLOSED = 0;
private static final long FLOOR_WAIT_TIME = 1000;
public static final long FLOOR_TRAVEL_TIME = 500;
private static final long INACTIVE_TIME = 1000 * 2;
private static final int MAX_OCCUPANCY = 20;
private int elevatorID;
private int doorState;
private int motionState;
private int motionDirection;
private volatile int currentFloorNumber;
private boolean requestDoorOpen;
private boolean[] destinationList = new
boolean[Building.MAX_FLOORS]; // of type int
private static ElevatorController elevatorController;
private Vector riders = new Vector();
private Thread activeElevator;
private Logger log;
private volatile boolean keepRunning;
private ElevatorState state = new ElevatorState();
public Elevator(int elevatorNumber){
elevatorID = elevatorNumber;
for(int i = 0; i < destinationList.length; i++){
destinationList[i] = false;
}
motionDirection = NO_DIRECTION;
currentFloorNumber = 1;
motionState = STOPPED;
doorState = DOOR_CLOSED;
}
public static void setElevatorController(ElevatorController
controller){
elevatorController = controller;
}
public int getElevatorNumber(){
return elevatorID;
}
public void setStopRunning(){
keepRunning = false;
}
public synchronized void setDestination(int floorNumber) {
if(riders.isEmpty() && motionState == STOPPED){
destinationList[floorNumber - 1] = true;
activeElevator.interrupt();
}else{
destinationList[floorNumber - 1] = true;
}
}
public synchronized void summonDestination(int floorNumber) throws
ElevatorMovingException {
if(getCurrentFloorNumber() != floorNumber ||
riders.isEmpty()){
destinationList[floorNumber - 1] = true;
activeElevator.interrupt();
}else{
throw new ElevatorMovingException();
}
}
public synchronized void requestOpenDoor() throws
ElevatorMovingException {
if(motionState == STOPPED)
requestDoorOpen = true;
else
throw new ElevatorMovingException();
}
public int getCurrentFloorNumber(){
return currentFloorNumber;
}
public void start() {
if(Simulator.debug) log = new Logger("Elevator" + elevatorID)
;
keepRunning = true;
if(activeElevator == null){
activeElevator = new Thread(this);
//activeElevator.setDaemon(true);
activeElevator.setPriority(Thread.NORM_PRIORITY - 1);
activeElevator.start();
}
} // end start
public void run() {
if(Simulator.debug) log.write("Starting elevator " +
elevatorID);
while(keepRunning){
switch(motionState){
case STOPPED:
if(Simulator.debug) log.write("Elevator " + elevatorID + " is
stopped");
if(riders.isEmpty() && !isDestination()){
motionDirection = NO_DIRECTION;
if(Simulator.debug) log.write("Elevator " + elevatorID + " is empty
and has no destination");
action(INACTIVE_TIME);
}else if(isArrived()){
if(Simulator.debug) log.write("Elevator " + elevatorID + " has
arrived on " + currentFloorNumber);
openDoor();
closingDoor();
removeDestination();
}else{
if(Simulator.debug) log.write("Elevator " + elevatorID + " is
continuing to travel");
travel();
}
break;
case MOVING:
if(isArrived()){
stopElevator();
}else{
travel();
}
break;
}
if(Simulator.debug) log.write(getState().toString());
}
if(log != null)log.close();
} // end run
public void leaveElevator(Person person) throws
DoorClosedException{
if(doorState == DOOR_OPEN)
riders.remove(person);
else{
if(Simulator.debug) log.write("Elevator " + elevatorID + " door is
closed can not leave.");
throw new DoorClosedException();
}
}
public void enterElevator(Person person)throws
ElevatorFullException, DoorClosedException{
if(doorState == DOOR_OPEN){
if(riders.size() < MAX_OCCUPANCY){
riders.add(person);
}else{
if(Simulator.debug) log.write("Elevator " + elevatorID + " is
full");
throw new ElevatorFullException();
}
}else{
if(Simulator.debug) log.write("Elevator " + elevatorID + " door is
closed can not enter.");
throw new DoorClosedException();
}
}
public ElevatorState getState(){
state.elevatorID = elevatorID;
state.currentFloorNumber = currentFloorNumber;
state.motionState = motionState;
state.motionDirection = motionDirection;
state.numberRiders = riders.size();
state.doorState = doorState;
StringBuffer sb = new StringBuffer();
for(int i = 0; i < destinationList.length; i++){
sb.append(destinationList[i] ? "1" : "0");
}
state.destinations = sb.toString();
return state;
}
private void action(long time){
try{
activeElevator.sleep(time);
}catch(InterruptedException ix){
//intentionally left empty
}
}
private synchronized boolean isArrived(){
boolean returnValue = false;
if(destinationList[currentFloorNumber - 1]){
returnValue = true;
motionState = STOPPED;
}
return returnValue;
}
private void moveUp(){
if(isDestinationAbove()){
if(currentFloorNumber != Building.MAX_FLOORS){
if(Simulator.debug) log.write("move up moves up");
action(FLOOR_TRAVEL_TIME);
++currentFloorNumber;
}
}else if(isDestinationBelow()){
if(Simulator.debug) log.write("moving up is changing
direction");
motionDirection = MOVING_DOWN; // someone missed floor change
direction
}else{
if(Simulator.debug) log.write("move up is stopping");
stopElevator(); // only destination is this floor
}
}
private void moveDown(){
if(isDestinationBelow()){
if(currentFloorNumber != 1){
if(Simulator.debug) log.write("move down moves down");
action(FLOOR_TRAVEL_TIME);
--currentFloorNumber;
}
}else if(isDestinationAbove()){
if(Simulator.debug) log.write("move down is changing
direction");
motionDirection = MOVING_UP; // someone missed floor change
direction
}else{
if(Simulator.debug) log.write("move down is stopping");
stopElevator(); // only destination is this flooor
}
}
private void openDoor(){
if(doorState == DOOR_CLOSED && motionState ==
STOPPED){
doorState = DOOR_OPEN;
notifyRiders();
notifyController();
action(FLOOR_WAIT_TIME);
}
}
private void closingDoor(){
do{
resetDoorRequest();
notifyRiders();
notifyController();
action(500);//give people a change to request door open
}while(isRequestDoorOpen());
doorState = DOOR_CLOSED;
}
// private synchronized void closeDoor(){
// doorState = DOOR_CLOSED;
// }
private synchronized void resetDoorRequest(){
requestDoorOpen = false;
}
private synchronized boolean isRequestDoorOpen(){
return requestDoorOpen;
}
private void notifyRiders(){
synchronized(riders){
for(int i = 0; i < riders.size(); i++){
((Person)riders.get(i)).attention();
}
}
}
private void notifyController(){
elevatorController.elevatorArrived(currentFloorNumber, this);
}
private synchronized void travel(){
if(isDestination()){
if(Simulator.debug) log.write("Elevator has a destination");
motionState = MOVING;
if(motionDirection == MOVING_UP){
if(Simulator.debug) log.write("Moving up");
moveUp();
}else if(motionDirection == MOVING_DOWN){
if(Simulator.debug) log.write("Moving Down");
moveDown();
}else if(isDestinationAbove()){
if(Simulator.debug) log.write("Setting direction up");
motionDirection = MOVING_UP;
moveUp();
}else if(isDestinationBelow()){
if(Simulator.debug) log.write("Setting direction down");
motionDirection = MOVING_DOWN;
moveDown();
}else{ //someone wants us where we are
if(Simulator.debug) log.write("someone wants on this floor " +
currentFloorNumber);
stopElevator();
}
}else{ // no destination don't move;
if(Simulator.debug) log.write("There is no destination");
motionDirection = NO_DIRECTION;
motionState = STOPPED;
action(INACTIVE_TIME);
}
}
private synchronized void removeDestination(){
destinationList[currentFloorNumber - 1] = false;
}
private void stopElevator(){
motionState = STOPPED;
}
private synchronized boolean isDestination(){
boolean returnValue = false;
for(int i = 0; i < destinationList.length; i++){
if(destinationList[i]){
returnValue = true;
break;
}
}
return returnValue;
}
private synchronized boolean isDestinationAbove(){
boolean returnValue = false;
for(int i = getCurrentFloorNumber(); i < destinationList.length;
i++){
if(destinationList[i]){
returnValue = true;
break;
}
}
return returnValue;
}
private synchronized boolean isDestinationBelow(){
boolean returnValue = false;
for(int i = getCurrentFloorNumber() - 2; i >= 0; i--){
if(destinationList[i]){
returnValue = true;
break;
}
}
return returnValue;
}
} // end Elevator
import java.util.*;
public class Floor {
private int floorNumber;
private volatile boolean summonUp;
private volatile boolean summonDown;
private Vector upWaiting = new Vector(); // of type Person
private Vector downWaiting = new Vector(); // of type Person
private static ElevatorController elevatorController;
private Logger log;
public Floor(int floorNumber){
this.floorNumber = floorNumber;
if(Simulator.debug) log = new Logger("Floor" +
this.floorNumber);
}
public void closeLog(){
if(log != null)log.close();
}
public boolean isSummonUp(){
return summonUp;
}
public boolean isSummonDown(){
return summonDown;
}
public static void setElevatorController(ElevatorController
controller){
elevatorController = controller;
}
public int getFloorNumber(){
return floorNumber;
}
public int getNumberWaitingUp(){
return upWaiting.size();
}
public int getNumberWaitingDown(){
return downWaiting.size();
}
public void summonElevatorUp(Person person) {
if(Simulator.debug) log.write("Summon up for person " +
person.getPersonNumber());
upWaiting.add(person);
if(!summonUp){//if already summoned no need to do it again
if(Simulator.debug) log.write("Light off summon UP for person " +
person.getPersonNumber());
elevatorController.summonElevatorUp(floorNumber, person);
summonUp = true;
}
}
public void summonElevatorDown(Person person) {
if(Simulator.debug) log.write("Summon down for person " +
person.getPersonNumber());
downWaiting.add(person);
if(!summonDown){ // id already summoned no need to do it
again
if(Simulator.debug) log.write("Light off summon DOWN for person " +
person.getPersonNumber());
elevatorController.summonElevatorDown(floorNumber, person);
summonDown = true;
}
}
public void elevatorArrivedUp(Elevator elevator) {
Person p = null;
summonUp = false;
synchronized(upWaiting){
for(int i = 0; i < upWaiting.size(); i++){
p = (Person)upWaiting.get(i);
p.elevatorArrived(elevator);
p.attention();
}
}
if(Simulator.debug) log.write("Elevator " +
elevator.getElevatorNumber() + " has arrived UP on " +
getFloorNumber());
} // end elevatorArrived
public void elevatorArrivedDown(Elevator elevator){
Person p = null;
summonDown = false;
synchronized(downWaiting){
for(int i = 0; i < downWaiting.size(); i++){
p = (Person)downWaiting.get(i);
p.elevatorArrived(elevator);
p.attention();
}
}
if(Simulator.debug) log.write("Elevator " +
elevator.getElevatorNumber() + " has arrived DOWN on " +
getFloorNumber());
}
public void stopWaiting(Person person) {
if(Simulator.debug) log.write("Person " + person.getPersonNumber()
+ " has stopped waiting on " + getFloorNumber());
upWaiting.remove(person);
downWaiting.remove(person);
} // end giveUp
} // end Floor
import java.util.*;
public class Building {
public static final int MAX_FLOORS = 10;
public static final int MAX_ELEVATORS = 9;
public ElevatorController elevatorController;
public volatile int peopleTakingStairs;
public volatile int peopleOutside = Simulator.MAX_PEOPLE;
public volatile int peopleWorking;
public Building(){
Vector floors = new Vector();
for(int i = 0; i < MAX_FLOORS; i++){
Floor f = new Floor(i + 1);
floors.add(f);
}
Vector elevators = new Vector();
for(int i = 0; i < MAX_ELEVATORS; i++){
Elevator e = new Elevator(i + 1);
elevators.add(e);
}
elevatorController = new ElevatorController(floors,
elevators);
Floor.setElevatorController(elevatorController);
Elevator.setElevatorController(elevatorController);
elevatorController.startElevators();
}
public ElevatorState getElevatorState(int elevatorNumber){
return elevatorController.getElevatorState(elevatorNumber);
}
public int getNumberWaitingUp(int floorNumber){
return elevatorController.getNumberWaitingUp(floorNumber);
}
public int getNumberWaitingDown(int floorNumber){
return elevatorController.getNumberWaitingDown(floorNumber);
}
public Floor getFloor(int floorNumber) {
return elevatorController.getFloor(floorNumber);
}
public Floor enterBuilding(){
return getFloor(1);
}
public void stopElevators(){
elevatorController.stopElevators();
}
} // end Building
import java.util.*;
//import java.swing.*;
public class Simulator {
public static volatile boolean debug = false;
public static final int MAX_PEOPLE = 200;
public static final int MAX_TIME = 60;
private static volatile int counter;
public static void stopProgram(){
counter = MAX_TIME;
}
public static int getTimeRemaing(){
return (MAX_TIME - counter)/2;
}
public static int getElapsedTime(){
return counter/2;
}
public static void main(String[] args) {
//Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
String source = null;
if(args.length >0)
source = args[0];
ElevatorConsole console = new ElevatorConsole(source);
Vector people = new Vector();
Building b = new Building();
console.setBuilding(b);
Person.setBuilding(b);
for(int i = 0; i < MAX_PEOPLE; i++){
Person p = new Person(i+1);
people.add(p);
p.start();
}
for(counter = 0; counter <= MAX_TIME; counter++){
console.updateDisplay();
try{
Thread.currentThread().sleep(500);
}catch(Exception e){
e.printStackTrace();
}
}
for(int i = 0; i < people.size(); i++){
((Person)people.get(i)).setStopRunning();
}
debug = false;
b.stopElevators();
System.out.println("Progam ended");
}
} // end Simulator