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.
Enter the password to open this PDF file:
File name:
-
File size:
-
Title:
-
Author:
-
Subject:
-
Keywords:
-
Creation Date:
-
Modification Date:
-
Creator:
-
PDF Producer:
-
PDF Version:
-
Page Count:
-
Preparing document for printing…
0%
Σχόλια 0
Συνδεθείτε για να κοινοποιήσετε σχόλιο