Java Reference
In-Depth Information
threads or the
IceCreamMan
thread could have started running immediately afterwards. In
addition, yielding is something you would normally do before you start (or in the middle of )
a lengthy or complex task—it is a way of being nice to other threads. However, this is not the
case here. Finally, if there are no other threads that can run, the JVM will immediately pass
control back to the while loop—this will result in the thread consuming as much CPU cycles
as are available; it can even lead to your computer having the appearance of hanging.
The
serveIceCream
method is the most interesting part of our code. Assuming that there is
currently a
Dish
in the queue, line 49
synchronize
s on that
IceCreamDish
instance. This has the
effect of forcing any
Child
objects that want to use the
IceCreamDish
instance to wait. Specifi-
cally, it causes line 55 in
Child
to pause until line 53 in
IceCreamMan
is reached or, if the
Child
thread had paused at line 60, it will not be able to resume until line 53 in
IceCreamMan
is
reached.
Conversely, if a
Child
instance is executing a method that
synchronize
s on the
IceCreamDish
, then hitting line 49 in
IceCreamMan
will cause
IceCreamMan
to wait until lines 50
through 61 in
Child
finish executing, or until the
Child
instance releases the lock on the
Ice-
CreamDish
by calling
wait
in line 55.
This is an example of the threads respecting each other's boundaries. By synchronizing on
the same object, the two threads can be assured that they will not be simultaneously modify-
ing or using the same object.
When the
IceCreamMan
owns the lock on the dish, he can fill it with ice cream, and then
notify the
Child
that it is available. This happens in line 52. After line 52 is run, the
Child
thread that was waiting on that particular plate will no longer be waiting—the JVM scheduler
will now be able to run it. However, until the
IceCreamMan
releases the lock on the dish at the
completion of line 53, the
Child
will not be able to regain the lock on the dish, so it will remain
blocked.
■
Note
You cannot call the
notify
method on an object unless you are in a block or a method that is
synchronized on that object.
34 /**
35 * Serve Ice Cream to a Child object.
36 */
37 private void serveIceCream() {
38 // get an ice cream dish
39 IceCreamDish currentDish = dishes.get(0);
40
41 // wait sometimes, don't wait sometimes
42 if (Math.random() > .5) {
43 delay();
44 }
45
46 String msg = "notify client that the ice cream is ready";
47 System.out.println("IceCreamMan: " + msg);
48