Solutions to selected exercises can be found in the electronic document The Thinking in Java Annotated Solution Guide, available for a small fee from www.BruceEckel.com.
- Inherit a class from Thread and override the run( )
method. Inside run( ), print a message, and then call
sleep( ). Repeat this three times, then return from
run( ). Put a start-up message in the constructor and override
finalize( ) to print a shut-down message. Make a separate thread
class that calls System.gc( ) and System.runFinalization( )
inside run( ), printing a message as it does so. Make several
thread objects of both types and run them to see what happens.
Experiment with different sleep times in Daemons.java to see what
- In Chapter 8, locate the GreenhouseController.java example, which
consists of four files. In Event.java, the class Event is based on
watching the time. Change Event so that it is a Thread, and change
the rest of the design so that it works with this new Thread-based
- Modify the previous exercise so that the java.util.Timer class is
used to run the system.
- Modify SimpleThread.java so that all the threads are daemon threads
and verify that the program ends as soon as main( ) is able to exit.
- Demonstrate that java.util.Timer scales to large numbers by creating
a program that generates many Timer objects that perform some simple task
when the timeout completes (if you want to get fancy, you can jump forward to
the “Windows and Applets” chapter and use the Timer objects
to draw pixels on the screen, but printing to the console is sufficient).
- Demonstrate that a synchronized method in a class can call a second
synchronized method in the same class, which can then call a third
synchronized method in the same class. Create a separate Thread
object that invokes the first synchronized method.
- Create two Thread subclasses, one with a run( ) that
starts up and then calls wait( ). The other class’s
run( ) should capture the reference of the first Thread
object. Its run( ) should call notifyAll( ) for the
first thread after some number of seconds have passed so that first thread can
print a message.
- Create an example of a “busy wait.” One thread sleeps for
awhile and then sets a flag to true. The second thread watches that flag
inside a while loop (this is the “busy wait”) and when the flag
becomes true, sets it back to false and reports the change to the
console. Note how much wasted time the program spends inside the “busy
wait” and create a second version of the program that uses
wait( ) instead of the “busy wait.”
- Modify Restaurant.java to use notifyAll( ) and observe
any difference in behavior.
- Modify Restaurant.java so that there are multiple
WaitPersons, and indicate which one gets each Order.
- Modify Restaurant.java so that multiple WaitPersons generate
order requests to multiple Chefs, who produce orders and notify the
WaitPerson who generated the request. You’ll need to use queues for
both incoming order requests and outgoing orders.
- Modify the previous exercise to add Customer objects that are also
threads. The Customers will place order requests with WaitPersons,
who give the requests to the Chefs, who fulfill the orders and notify the
appropriate WaitPerson, who gives it to the appropriate
- Modify PipedIO.java so that Sender reads and sends lines from
a text file.
- Change DiningPhilosophers.java so that the philosophers just pick
the next available chopstick (when a philosopher is done with their chopsticks,
they drop them into a bin. When a philosopher wants to eat, they take the next
two available chopsticks from the bin). Does this eliminate the possibility of
deadlock? Can you re-introduce deadlock by simply reducing the number of
- Inherit a class from java.util.Timer and implement the
requestStop( ) method as in Stopping.java.
- Modify SimpleThread.java so that all threads receive an
interrupt( ) before they are completed.
- Solve a single producer, single consumer problem using wait( )
and notify( ). The producer must not overflow the receiver's buffer,
which can happen if the producer is faster than the consumer. If the consumer is
faster than the producer, then it must not read the same data more than once. Do
not assume anything about the relative speeds of the producer or