A bus service travels between a series of equidistant bus stops numbered 1, 2, 3, 4, 5, as in Figure 3. When the bus arrives at either end of its route (stop 1 or stop 5) it turns around and goes back the other way, and continues to do this until it is no longer required. The direction from stop 1 to stop 5 is called the UP direction; the other way is the DOWN direction.
UP -> <- DOWN
1_________2_________3_________4_________5
Passengers arrive at a departure bus stop, wait for a bus that is going in the correct direction and when the bus arrives they get on, travel to their destination stop and get off.
The bus waits at each stop for a fixed amount of time, to allow passengers to get on or off, then the doors are closed and it moves off to the next stop. The bus has a maximum capacity so, if it is full, some waiting passengers may not be able to get on.
The supplied skeleton code ignores the fact that passengers want to travel in a particular direction (UP or DOWN). This means that passengers may actually travel the wrong way for part of the time before eventually reaching their destination. In due course you will rectify this.
A skeleton of a concurrent application that simulates such a system is provided in the NetBeans project BusService which consists of the following classes.
Class Passenger simulates each passenger as a separate thread. Passengers have unique IDs (so that their behaviour can be traced) and they wish to move from a departure bus stop to a destination bus stop. The ID and both stops are given to the constructor. All a passenger thread does is to board the bus at the start bus stop and exit it at the destination bus stop.
Class Bus simulates the bus, which is a resource shared by passengers and the control system. It provides three methods. Methods getOn and getOff are called by the passengers, giving as argument the departure and destination bus stop, respectively. Method move is called by the control system whenever the waiting time has elapsed and the bus has to move to the next bus stop.
Class Control represents the bus control system as a thread. The control system basically keeps repeating two steps – wait a fixed amount of time and move the bus one stop in the appropriate direction – until all passengers have arrived at their destination bus stops.
Class Main brings everything together. It declares some constants representing the various parameters of the simulation (waiting time at each bus stop, number of passenger threads etc.). Although these parameters can be changed, you should retain the existing values until you are confident that you have the application working correctly. You have to add code so that the main application thread first creates the control and passenger threads and then waits for all passenger threads to terminate, at which point it tells the control thread that it should terminate too.
The expected output for the partly implemented application would look similar to Figure 2. The lines show the ordering of events, and events happening at the same bus stop are aligned vertically. In the example, the bus has the capacity for two passengers (shown by a dot for each empty seat and an asterisk for each passenger in the bus). Passengers get off two bus stops after the bus stop where they get on (though sometimes they start off going in the wrong direction).
Bus Stops
1---------------2---------------3---------------4---------------5
[..]BUS> arrives
P1 arrives
P1 gets on
P2 arrives
P4 arrives
P6 arrives
P5 arrives
P3 arrives
[*.]BUS> leaves
[*.]BUS> arrives
P2 gets on
[**]BUS> leaves
[**]BUS> arrives
P1 gets off
P4 gets on
[**]BUS> leaves
[**]BUS> arrives
P2 gets off
[*.]BUS> leaves
[*.]BUS> arrives
P6 gets on
P6 gets off
P4 gets off
[..]BUS> leaves
[..]BUS> arrives
[..]BUS> leaves
[..]BUS> arrives
P3 gets on
[*.]BUS> leaves
[*.]BUS> arrives
P5 gets on
[**]BUS> leaves
[**]BUS> arrives
P3 gets off
P5 gets off
Figure 2 Output from running the partially implemented application