|
The following program is a simple emulation of a steam
boiler. The boiler has a number of burners (this is a big
boiler!), each one of which is programmed to burn fuel to
keep the steam pressure up, unless the pressure exceeds a
certain safety limit.
Class SteamBoiler
represents the boiler, and class Burner
represents a single burner. Each burner runs as a separate
thread, and calls its burn()
method to "burn fuel". The burn()
method has a check to make sure that the pressure does not go
beyond the safety limit.
You'll note that each burner just kicks in once, and then
stops -- i.e. its thread dies. This is not realistic, but is
done to keep things relatively simple. When all the threads
have died, the main program prints out the resulting
pressure, and exits.
Here's the code:
package unsynchronized;
/**
* NOTE: This implementation of the SteamBoiler class is implemented
* without regard to synchronization. Because of this, it fails
* to maintain boiler pressure below the safety limit.
*/
public class SteamBoiler
{
public static final int PRESSURE_LIMIT = 20;
public static final int BURNER_COUNT = 10;
public Burner[] start()
{
Burner[] burners = new Burner[BURNER_COUNT];
for (int burner = 0; burner < BURNER_COUNT; burner++)
{
burners[burner] = new Burner(this);
burners[burner].start();
}
return burners;
}
public int getPressure()
{
return m_pressure;
}
public void setPressure(int pressure)
{
m_pressure = pressure;
}
public static void main(String[] args)
{
SteamBoiler boiler = new SteamBoiler();
Burner[] burners = boiler.start();
for (int burner = 0; burner < BURNER_COUNT; burner++)
{
try
{
burners[burner].join(); // Wait for thread to finish
}
catch (InterruptedException e)
{
// This thread was interrupted.
}
}
System.out.println("Pressure reads " + boiler.getPressure() +
", limit is " + PRESSURE_LIMIT);
}
/////// Data //////
private int m_pressure = 0;
}
class Burner extends Thread
{
public static final int PRESSURE_INCREMENT = 15;
public Burner(SteamBoiler boiler)
{
m_boiler = boiler;
}
public void run()
{
burn();
}
private void burn()
{
if (m_boiler.getPressure() <
SteamBoiler.PRESSURE_LIMIT - PRESSURE_INCREMENT)
{
// Wait to simulate delay
try
{
sleep(100);
}
catch (InterruptedException e)
{
// Ignore
}
m_boiler.setPressure( m_boiler.getPressure() +
PRESSURE_INCREMENT );
}
}
///// Private data //////
private SteamBoiler m_boiler;
}
|
However, when the program is run, you'll find that it
outputs the following:
Pressure reads 150, limit is 20
Here's an applet that uses the above class and displays
the boiler pressure in a more graphical form:
Here's the source
for this applet.
(Perhaps I should add some explosive effects?)
So what's
going on?
|