Solutions Manual: Chapter 21 Big Java, by Cay Horstmann 22
Review Exercises
R21.1
The reason is that the code calls run, not start, on the thread. The run method runs the code in the same thread.
R21.3
There are one MAIN thread and other threads for the GUI. Example, when one does not implement the EXIT_ON_CLOSE feature, the program will not end after a user closes the GUI window.
R21.5
Suppose a long computation is carried out in a thread, has not yet completed, and the user is no longer interested in the result and wishes to cancel the computation. Then, it is time to terminate the thread.
R21.7
From Thread-0 or Thread-2. (Waiting and sleeping threads are not runnable...)
R21.9
A race condition occurs if the effect of multiple threads on shared data depends on the order in which the threads are scheduled.
There is no simple recipe to avoid race conditions. You can often, but not always, avoid race conditions by synchronizing certain methods.
R21.11
The sleep method puts the current thread to sleep for a given number of milliseconds. The wait method makes the thread wait and allows another thread to acquire the object lock. In other word, sleep will sleep until a given time and wait will wait until some other threads to notify.
R21.13
Make t2 transfer $500 each from account0 and account1 to account2, and change the transfer like this:
from1.withdraw(amount);
to.deposit(amount);
from2.withdraw(amount);
to.deposit(amount);
R21.15
After the sleeping thread wakes up, it will do its job and call isInterrupted method inside the pause method. The isInterrupted method will return true since the mousePressed method calls the interrupt method on the animation thread. Then, the pause method will throw a new InterruptedException which throw up to the try-catch block inside the run method. Now, the run method catches the exception and ends the thread.
When the thread is not sleeping, it does the same thing that sleeping thread does after the sleeping thread wakes up.
Programming Exercises
P21.1
Queue.java
import java.util.ArrayList;
/**
This class implements the FIFO queue data structure.
*/
public class Queue
{
/**
Constructs the maximum size of the queue to deafult size.
*/
public Queue()
{
size = DEAFULT_SIZE;
queue = new ArrayList(size);
}
/**
Constructs the maximum size of the queue to the given size.
@param aSize the maximum size of the queue
*/
public Queue(int aSize)
{
size = aSize;
queue = new ArrayList(size);
}
/**
Adds a string into the queue.
@param item the item to add
*/
public synchronized void add(String item) throws InterruptedException
{
while (isFull())
wait();
queue.add(item);
notifyAll(); // notify all others that the queue is not empty
}
/**
Removes one item from the queue.
@return the first item of the queue
*/
public synchronized String remove() throws InterruptedException
{
while (isEmpty())
wait();
notifyAll(); // notify all others that the queue is not full
return queue.remove(0).toString();
}
/**
Check if the queue is empty.
@return true if the queue is empty, else false
*/
public boolean isEmpty()
{
return queue.isEmpty();
}
/**
Check if the queue is full.
@return true if queue size equals to maximum size, else false
*/
public boolean isFull()
{
return queue.size() == size;
}
private ArrayList queue;
private int size = 0;
private static final int DEAFULT_SIZE = 10;
}
ConsumerThread.java
/**
This class will keep removing things from the queue
*/
public class ConsumerThread extends Thread
{
/**
Constructs the consumer with a queue and count.
@param aQueue the queue that the consumer going to consume from
@param count the number of time that consumer going to consume
*/
public ConsumerThread(Queue aQueue, int aCount)
{
count = aCount;
queue = aQueue;
}
public void run()
{
try
{
for (int i = 0; i < count & !isInterrupted(); i++)
{
System.out.println("Consumer: " + queue.remove());
sleep(DELAY);
}
}
catch (InterruptedException exception)
{
}
}
private Queue queue = null;
private int count;
private static final int DELAY = 1000;
}
ProducerThread.java
import java.util.Date;
/**
This class will keep putting things into the queue.
*/
public class ProducerThread extends Thread
{
/**
Constructs the producer with a queue and count.
@param aQueue the queue that the consumer going to consume from
@param count the number of time that consumer going to consume
*/
public ProducerThread(Queue aQueue, int aCount)
{
count = aCount;
queue = aQueue;
}
public void run()
{
try
{
for (int i = 0; i < count & !isInterrupted(); i++)
{
String item = new Date().toString();
System.out.println("Producer: " + item);
queue.add(item);
sleep(DELAY);
}
}
catch (InterruptedException exception)
{
}
}
private Queue queue = null;
private int count;
private static final int DELAY = 1000;
}
AddCoinThread.java
/**
This class will keep putting things into the queue.
*/
public class AddCoinThread extends Thread
{
/**
Constructs the producer with a queue and count.
@param aQueue the queue that the consumer going to consume from
@param count the number of time that consumer going to consume
*/
public AddCoinThread(Purse aPurse, Coin aCoin)
{
purse = aPurse;
coin = aCoin;
}
public void run()
{
try
{
while (true)
{
System.out.println("Add " + coin.getName());
purse.addCoin(coin);
sleep(DELAY);
}
}
catch (InterruptedException exception)
{
}
}
private Purse purse;
private Coin coin;
private static final int DELAY = 1000;
}
ExP21_1.java
/**
This program demonstrates how to handle the classic race condition
problem, consumer and producer.
*/
public class ExP21_1
{
public static void main(String args[])
{
Queue q = new Queue(QUEUE_MAX_SIZE);
ProducerThread producer = new ProducerThread(q, NUM_OF_ITERATION);
ConsumerThread consumer = new ConsumerThread(q, NUM_OF_ITERATION);
producer.start();
consumer.start();
}
private static int QUEUE_MAX_SIZE = 10;
private static int NUM_OF_ITERATION = 1000;
}
P21.3
Coin.java
/**
A coin with a monetary value.
*/
public class Coin
{
/**
Constructs a coin.
@param aValue the monetary value of the coin.
@param aName the name of the coin
*/
public Coin(double aValue, String aName)
{
value = aValue;
name = aName;
}
/**
Gets the coin value.
@return the value
*/
public double getValue()
{
return value;
}
/**
Gets the coin name.
@return the name
*/
public String getName()
{
return name;
}
public boolean equals(Object otherObject)
{
Coin other = (Coin)otherObject;
return name.equals(other.name) & value == other.value;
}
private double value;
private String name;
}
Purse.java
import java.util.ArrayList;
/**
A purse holds a collection of coins.
*/
public class Purse
{
/**
Constructs an empty purse.
*/
public Purse()
{
coins = new ArrayList();
}
/**
Add a coin to the purse.
@param aCoin the coin to add
*/
public synchronized void addCoin(Coin aCoin) throws InterruptedException
{
coins.add(aCoin);
notifyAll();
}
/**
Remove a coin from the purse.
@param return the coin that removed from the purse
*/
public synchronized Coin removeCoin() throws InterruptedException
{
while (coins.isEmpty())
wait();
return (Coin)coins.remove(0);
}
/**
Get the total value of the coins in the purse.
@return the sum of all coin values
*/
public double getTotal()
{
double total = 0;
for (int i = 0; i < coins.size(); i++)
{
Coin aCoin = (Coin)coins.get(i);
total = total + aCoin.getValue();
}
return total;
}
private ArrayList coins;
}
AddCoinThread.java
/**
This class will keep putting coins into the purse.
*/
public class AddCoinThread extends Thread
{
/**
Constructs the producer with a purse and a coin.
@param aPurse the purse that has all the coins
@param aCoin the coin that is going to put into the purse
*/
public AddCoinThread(Purse aPurse, Coin aCoin)
{
purse = aPurse;
coin = aCoin;
}
public void run()
{
try
{
while (true)
{
System.out.println("Adds " + coin.getName());
purse.addCoin(coin);
sleep(DELAY);
}
}
catch (InterruptedException exception)
{
}
}
private Purse purse;
private Coin coin;
private static final int DELAY = 1000;
}
RemoveCoinThread.java
/**
This class will keep removing coins from a purse.
*/
public class RemoveCoinThread extends Thread
{
/**
Constructs the producer with a purse.
@param aPurse the purse that has all the coins
*/
public RemoveCoinThread(Purse aPurse)
{
purse = aPurse;
}
public void run()
{
try
{
while (true)
{
System.out.println("Removes " + purse.removeCoin().getName());
sleep(DELAY);
}
}
catch (InterruptedException exception)
{
}
}
private Purse purse;
private Coin coin;
private static final int DELAY = 1000;
}
ExP21_3.java
/**
This program demonstrates how two threads keep adding coins to the purse
while one other thread keeps removing coins from the purse.
*/
public class ExP21_3
{
public static void main(String args[])
{
Purse myPurse = new Purse();
AddCoinThread addPennyThread = new AddCoinThread(myPurse,
new Coin(PENNY_VALUE, "penny"));
AddCoinThread addQuarterThread = new AddCoinThread(myPurse,
new Coin(QUARTER_VALUE, "quarter"));
RemoveCoinThread removeCoinThread = new RemoveCoinThread(myPurse);
addPennyThread.start();
addQuarterThread.start();
removeCoinThread.start();
}
private static double PENNY_VALUE = 0.01;
private static double NICKEL_VALUE = 0.05;
private static double DIME_VALUE = 0.1;
private static double QUARTER_VALUE = 0.25;
}
P21.5
CarApplet.java
import javax.swing.JApplet;
import javax.swing.JComponent;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.Color;
/**
This applet shows two running car runs into the wall.
*/
public class CarApplet extends JApplet
{
public void init()
{
delay = 100;
Dimension d = getSize();
car1 = new SmartCarThread(100, 100, 0.4, d);
car2 = new SmartCarThread(100, 200, 0.2, d);
car1.start();
car2.start();
contentPane = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
car1.draw((Graphics2D)g);
car2.draw((Graphics2D)g);
}
};
contentPane.setBackground(Color.green);
setContentPane(contentPane);
}
public void update(Graphics g)
{
contentPane.repaint();
repaint();
}
public void paint(Graphics g)
{
repaint();
}
public void stop()
{
car1.interrupt();
car2.interrupt();
}
JComponent contentPane;
protected int delay = 100;
private CarThread car1;
private CarThread car2;
}
CarThread.java
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
/**
A moving car shape that can be start anywhere on the screen.
The car will run into the wall without stopping.
*/
public class CarThread extends Thread
{
/**
Constructs a car with a given top left corner
@param x the x coordinate of the top left corner
@param y the y coordinate of the top left corner
@param speed the speed of the car
*/
public CarThread(double x, double y, double speed)
{
dx = speed;
xLeft = x;
yTop = y;
}
public void run()
{
while (true)
{
move();
}
}
/**
Move the car according to the speed.
*/
public void move()
{
xLeft += dx;
System.out.println();
}
/**
Draws the car
@param g2 the graphics context
*/
public void draw(Graphics2D g2)
{
Rectangle2D.Double body
= new Rectangle2D.Double(xLeft, yTop + 10, 60, 10);
Ellipse2D.Double frontTire
= new Ellipse2D.Double(xLeft + 10, yTop + 20, 10, 10);
Ellipse2D.Double rearTire
= new Ellipse2D.Double(xLeft + 40, yTop + 20, 10, 10);
// the bottom of the front windshield
Point2D.Double r1
= new Point2D.Double(xLeft + 10, yTop + 10);
// the front of the roof
Point2D.Double r2
= new Point2D.Double(xLeft + 20, yTop);
// the rear of the roof
Point2D.Double r3
= new Point2D.Double(xLeft + 40, yTop);
// the bottom of the rear windshield
Point2D.Double r4
= new Point2D.Double(xLeft + 50, yTop + 10);
Line2D.Double frontWindshield
= new Line2D.Double(r1, r2);
Line2D.Double roofTop
= new Line2D.Double(r2, r3);
Line2D.Double rearWindshield
= new Line2D.Double(r3, r4);
g2.draw(body);
g2.draw(frontTire);
g2.draw(rearTire);
g2.draw(frontWindshield);
g2.draw(roofTop);
g2.draw(rearWindshield);
}
/**
Returns the X position on the display window of the car.
@return the x position of the car
*/
public double getX()
{
return xLeft;
}
public void setSpeed(double aX)
{
dx = aX;
}
public double getSpeed()
{
return dx;
}
private double dx = 0.01;
private double xLeft;
private double yTop;
}
SmartCarThread.java
import java.awt.Dimension;
/**
A car shape that can be positioned anywhere on the screen.
The car will reverse it's direction when it hits the edge
of the window.
*/
public class SmartCarThread extends CarThread
{
/**
Constructs a car with a given top left corner
@param x the x coordinate of the top left corner
@param y the y coordinate of the top left corner
@param speed the speed of the car
*/
public SmartCarThread(double x, double y, double speed, Dimension aDim)
{
super(x,y,speed);
d = aDim;
}
/**
Move the car according to the speed. The car will change direction
when it hits the edge of the window.
*/
public void move()
{
if (getX() <= 0 || getX() >= d.getWidth() - 60)
reverseDirection();
super.move();
}
/**
Reverses the direction of the car.
*/
public void reverseDirection()
{
setSpeed(-getSpeed());
}
private Dimension d;
}
CarApplet.htm
<applet code="CarApplet.class" width="300" height="300">
</applet>
P21.7
Find.java
/**
Finds a target string from a file. Then, the program will print out the
line contains the target string.
*/
public class Find extends Thread
{
public static void main(String argv[])
{
for (int i = 1; i < argv.length; i++)
{
new FindThread(argv[0], argv[i]).start();
}
}
}
FindThread.java
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.StringTokenizer;
/**
Finds a target string from a file. Then, the program will print out the
line contains the target string.
*/
public class FindThread extends Thread
{
/**
Constructs a Find object with a target string and file name.
@param aTarget the target string that needs to be search
@param aFilename the file name that needs to count word
*/
public FindThread(String aTarget, String aFilename)
{
target = aTarget;
filename = aFilename;
}
public void run()
{
String line;
try
{
fin = new FileReader(filename);
in = new BufferedReader(fin);
while ((line = in.readLine()) != null)
{
if ((line.indexOf(target)) != -1)
System.out.println(filename + ": " + line);
}
}
catch (FileNotFoundException e)
{
System.out.println(filename + " not found!");
}
catch (IOException e)
{
System.out.println(e);
}
}
private String target;
private String filename;
private FileReader fin;
private BufferedReader in;
}
e0301.txt
Hi All
After today's meeting, everyone knows his/her rights and wrongs. Please make change to your ER and draw them on Word Document and Excel!
Then, you may start the fun part of this project, fabricate data by writing Java Programs.
In the attachment, I have two examples. Please read them over and see how you should write the Java Programs.
I have a CommonCreator.java.