Question 2.doc (65K) - Student of Fortune

tamerunSoftware and s/w Development

Aug 15, 2012 (4 years and 10 months ago)

218 views

Question 2


A NetBeans project
TMA03Q2

is provided.


The Ferry Boat Problem


In this question you will develop a simple simulation of a ferry that shuttles

back and forth across a stretch of water. At a given moment the ferry is in

one of two states:
EASTB
OUND
or
WESTBOUND
:


EASTBOUND
means that the ferry is either at the west landing stage, ready

to cross eastwards (Figure 1) or actually doing so (Figure 2)


WESTBOUND
means the ferry is either at the east landing stage, ready to

cross westwards or actually

doing so.



Figure1 The ferry
EASTBOUND
at the west landing stage



Figure2 The ferry crossing
EASTBOUND


The users of the ferry are simulated by
Passenger
threads, who may

board while the ferry is paused at a landing stage (but not of course while it

i
s crossing). To simulate boarding, they invoke the
board(Passenger)

method on the
Ferry
object. When a passenger invokes this method, it

passes itself as argument so the ferry can add them to a passenger list.

Passengers may be
EASTBOUND
or
WESTBOUND
trave
llers.
EASTBOUND

travellers arrive at the west landing stage and may not board unless the state

of the ferry is
EASTBOUND
and the ferry is not yet crossing. Similarly,

WESTBOUND
travellers arrive at the east landing stage and may not board

unless the ferry

is
WESTBOUND
and is not yet crossing (Figure 3).




Figure 3
WESTBOUND
passengers may board only if the ferry is
WESTBOUND
and

at the east landing stage


The passage of the ferry across the water is simulated by a

FerryConductor
thread, which invokes a
c
ross()
method on the

Ferry
object.


In the simulation, time is speeded up considerably compared with real life so

our experiments will not take too long to run.

The project we have supplied is an incomplete prototype. It will compile and

run but doesn

t fu
lly implement all the conditions described above. You are

asked to complete the coding, so that all the conditions are met, and then to

make some further changes to improve the realism of the simulation.


(a)
Open the project
TMA03Q2
and expand it fully in

the Projects window.

It contains the following classes. Note that the only one of these you will be

asked to change is
Ferry
.


In package
utilities
:

Delays

This class exists only to provide two static utility methods used by other

classes in the project:

delay(int ms)
, which introduces a sleep of duration
ms

milliseconds

randomDelay(int ms)
, which introduces a sleep of random

duration between
0
and
ms
milliseconds.

The classes that use these methods contain what is known as a
static

import
:

import static u
tilities.Delays.*;

The static import allows the methods to be called from within those

classes just by using the simple name of a method, e.g.
delay(2000);

rather than the quali
fi
ed name
utilities.Delays.delay(2000);
.

This helps to keep the code clear and
uncluttered.

Direction

This is an
enum
, a special kind of class that you will not have met in the

module text but which is quite easy and intuitive to understand. An enum

simply de
fi
nes a new Java type that can only take one of a
fi
xed range of

values list
ed in the enum de
fi
nition. For example we could de
fi
ne an

enum named
Season
with values
SPRING
,
SUMMER
,
AUTUMN
and

WINTER
.


In our case
Direction
de
fi
nes just two values,
EASTBOUND
and

WESTBOUND
, which represent the two possible directions of the ferry and

passengers.

The classes that use
Direction
have a static import

import static utilities.Direction.*;

which allows us to refer to the directions using just the simple names

EASTBOUND
and
WESTBOUND
.

In package
tma03q2
:

.
Ferry

An instance of this class repr
esents the ferry.

Ferry
has an instance variable
Direction direction
with accessor

methods
getDirection()
and
setDirection(Direction)
.

There is also a helper method
swapDirection()
that switches the

direction, from
EASTBOUND
to
WESTBOUND
or vice versa.

A s
econd instance variable
List<Passenger> passengerList

stores references to the passengers currently aboard.

This class has methods
board(Passenger)
, which will be invoked by

a passenger thread, and
cross()
, which will be invoked by the

conductor thread. Th
ere is no method that passenger threads invoke to

disembark; instead the
cross()
method clears the passenger list at the

end of its execution.

.
FerryConductor

An instance of this class represents the ferry conductor.

A
FerryConductor
has a
Ferry
that repr
esents the ferry the

conductor is responsible for. The class
FerryConductor
extends

Thread
and has a
run()
method that uses a
for
loop that repeatedly

delays for 2 seconds, then invokes
cross()
on its ferry. The
cross()

method currently performs 10 ferry c
rossings,
fi
ve in each direction. We

estimate this will be suf
fi
cient for testing purposes but you can increase

the number if necessary.

.
Main

The main()
method in this class
fi
rst creates an instance of
Ferry
and

an associated
FerryConductor
, and sets th
e latter running. It then

creates six passengers, bound alternately east and west, starting each one

as it is created. To simulate the random arrival of passengers that would

be observed in real life a random delay of up to 2000 milliseconds is

introduced
in between the creation of each
Passenger
thread. You may

wish to adjust this delay to test your code further.

.
Passenger

An instance of this class represents a passenger.

Passenger
has three instance variables:

Direction direction
, representing the direc
tion in which

the passenger is travelling

int idNum
, representing a passenger

s identity

Ferry ferry
, which represents the ferry.



None of these variables has a setter, since they should not change once

the
Passenger
has been created. However, there are g
etters for the

direction and identity number, and a three
-
argument constructor.

Passenger extends
Thread
and has a
run()
method that reports the

passenger

s arrival at the landing stage and then invokes the

board(Passenger)
method on the ferry object.


i
)

Begin by opening each of the classes described above and reading

quickly through them to get a general idea of how they work, but

without going into too much detail at this stage.

Now run the project. You should
fi
nd the simulation is fatally
fl
awed.

The p
assenger threads can board the ferry without regard to whether the

ferry is at the correct landing stage, and even while it is in midcrossing.

Obviously, this violates the real
-
life conditions we are trying

to model.

Copy a suitable extract from the output

into your
TMA 03 Solution

Document
and explain brie
fl
y how it demonstrates that the existing

program allows passengers to board when it should be impossible. (If

the output does not demonstrate what it should, try shortening the

random delay between the c
reation of passengers in the
main()

method.)


ii)
The
fi
rst step towards
fi
xing these de
fi
ciencies is to make it impossible

for a passenger thread to execute
board(Passenger)
at the same

time as
cross()
is being executed by the ferry conductor thread.

Make
the required changes to the code of the
board()
and
cross()

methods in class
Ferry
. Note that all you need do is insert an extra

keyword in the header of each method.

In your
TMA 03 Solution Document
include the two lines that you

changed and an extract fr
om the output when you run the project again,

demonstrating that now travellers don

t board while the ferry is

crossing. (Passengers will still be able to board from the wrong bank

though


that problem isn

t
fi
xed yet.)


iii
)

Further modi
fi
cations are nee
ded to enforce the requirement that a

passenger cannot board if the ferry is not at the appropriate landing

stage.

Passenger
and
Ferry
both have a
getDirection()
method.

Therefore it is possible for the
board(Passenger)
method to obtain

the direction of th
e passenger and the current direction of the ferry, and

compare the two. If they are not the same, the passenger thread should

be made to wait.

Once a passenger thread is waiting, there has to be some means of

waking it up again when the condition of the f
erry changes and it

becomes permissible for the passenger to board. The direction of the

ferry is changed at the end of the
cross()
method, and at that point a

line of code must be added that will wake up any waiting threads.

Make the necessary amendments
to the code. Copy the modi
fi
ed

board(Passenger)
and
cross()
methods into your
Solution

Document
, highlighting the changes you have made.


iv)
A real ferry would only be permitted to carry up to a certain maximum

number of passengers per trip, for safety re
asons. Change the code

again so that at most two passengers can board per trip. (Obviously, the

maximum might be considerably greater than this in real life but we

need to keep the numbers small in the simulation so it doesn

t get

unwieldy.)

Make the requi
red alterations and copy the code you have changed into

your
Solution Document
.


In the
main()
method, shorten the random delay to 500 milliseconds

or less (this is so that enough travellers bound the same way arrive

together to test the restriction to two

passengers per crossing) then run

the program again. Copy enough of the output into your
Solution

Document
to show that the
simulation is working correctly, that is

passengers can board only from the correct bank and no
more than two

are carried per ferry

trip. Indicate where in the output it is possible to

observe
that only two passengers were allowed to board at once.


(b)
In this part we consider a possible extension to the Ferry Boat Problem.

In the existing model the passengers synchronize with the fe
rry conductor, in

order to board only when appropriate. However, the ferry conductor does not

synchronize with the passengers but simply maintains a
fi
xed schedule, thus

potentially making many pointless trips. How might the conductor be made

to operate mo
re ef
fi
ciently?


i)

One suggestion would be to have a policy that the ferry must never set

off empty, so if
cross()
is invoked and the passenger list is empty the

conductor thread is made to wait. Explain in one sentence why this

simple policy would not be sa
tisfactory (at least, not in real life). We

are not looking for anything particularly deep or technical: simply ask

yourself what the result of such a policy could be.


ii)

Make changes to the
Ferry
class so that when
cross()
is invoked the

ferry conductor thr
ead will be made to wait unless one of the following

conditions apply:

at least one passenger is on board

at least one passenger has invoked
board(Passenger)
but has

been made to wait.


If your solution is correct you should
fi
nd when you run the program t
hat all

six travellers cross in some order, then the ferry waits inde
fi
nitely. To stop

the program, select Stop Build/Run from the NetBeans Run menu or click

on the cross to the right of the running task display in the bottom of the

NetBeans window. You ma
y need to stop more than one project running if

you ran your program several times.


(c)
You might suppose that the only way a thread that has been suspended

by
wait()
can be woken is by some other thread invoking
notify()
or

notifyAll()
. Perhaps surprisin
gly, it turns out that
spurious wakeups

may be possible, in which a thread is awakened even though there has been

no noti
fi
cation. (This can happen in other languages, not just Java.)


However, if the section of code where the call to
wait()
occurs has bee
n

written correctly, spurious wakeups present no problem.
Explain brie
fl
y why

not.