©1994-2003 Kevin Boone
Home     Section index     K-Zone home Simple Java programs

Site search

Glossary
Confused by computer jargon? Look it up!

Shameless plug


Now available!

Articles
- Ten-minute guide to setting up a WAP site

- Talk like your boss: new developments in managerese

More...

Development
File handling in the Linux kernel

Java development for the Sony-Ericsson P800

SunONE Application Server 7 FAQ

More...

Linux
Using Linux with the Treo 600

- Linux on the Tecra M1

- Some notes on openzaurus

More...

Download
Java stuff

Linux stuff

More...

(Please read the download policy)

Home automation
The X10 system

Linux TW723 driver

More...

The K-Zone
K-Zone computing

K-Zone law

K-Zone education and science

K-Zone motorcycles

K-Zone DIY

K-Zone railways

K-Zone martial arts

About the author

K-Zone home page

 
Software development
Computing
Hello1.java
Add1.java
Add1_1.java
AwtTest.java
Button1.java
Button2.java
Calculator.java
CalculatorApp.java
ClockApplet.java
CountSpace1.java
DateTime.java
Div1.java
DoNothing.java
Factorial1.java
Factorial2.java
FontChooser.java
IfTest.java
Inheritance1.java
Loan.java
DiceThrower.java
MultiplicationTable.java
Reverse1.java
SoundApplet.java
Stressometer.java
TextReaderTest.java
WebMerge.java
Zener.java
`Queue' example program: simulate queuing; demonstrates multi-threaded simulations

Queue.java

/*==============================================================================
Queue.java

This is a simple program that simulates `Queuing problems'. People who are
more familiar with American English rather than British English will perhaps
be familiar with the term `waiting in line' rather than `queuing'. In
Britain the word `queue' is a verb and a noun (we queue, and we join a queue).
Anyway, queueing problems are very important in business. Consider a situation
where you have a telephone helpdesk. There is a person answering calls, and
new people calling all the time. Calls can be held in a queue, but if you
make people wait too long they will get bored and hang up. This will lead
to dissatisfaction with your business. On the other hand, if you employ
more people to answer calls, sometimes they will have nothing to do. The
optimum situation is to get the best compromise between the queue being
empty (i.e., your staff not having anything to do) and the queue being
full (i.e., your customers getting cross). Programs like this one
can be used to investigate queueing experimentally. 

From a Java perspective, this program is a demonstration of multithreading.
The main applet creates two new threads of execution; one represents the
`supplier' (that is, the process that puts people on the queue) and the
other the consumer (that is, the process that takes people off the queue.
The supplier and the consumer may work at different speeds. The program
displays the number of people in the queue at any given time, and the
number of times people were turned away from the queue, or the queue
was found to be empty and the consumer had nothing to do.

Although simple, the princples embodied by this applet are very 
important. The use of different threads that can communicate with one
another is a very effective way to make programs more responsive.

The applet's display looks like this:


(If you aren't looking at the HTML version of this file, you won't see the picture) The way the applet is currently configured, the queueing problem is set up as follows: The maximum number of people in the queue is ten. New people arrive at random time intervals between 0 and 800 seconds. It takes a random length of time between 0 and 1000 seconds to deal with each person that joins the queue. This means that the queue will gradually become full, and people will start being turned away. To speed things up, I have reduced the time scale by a factor of 1000, that is, I have used 800 milliseconds rather than 800 seconds. Otherwise it would take several weeks to get any results. It is very easy to change these parameters by modifying the values assigned to the attributes in the constructor. Kevin Boone, July 1999 ==============================================================================*/ import java.applet.Applet; import java.awt.*; public class Queue extends Applet { /*============================================================================== Attributes of Queue class All these attributes are initialized in the constructor ==============================================================================*/ // numberInQueue is the number of people currently waiting in the queue int numberInQueue; // queueLimit is the number of people that the queue can accomodate int queueLimit; // queueEmpty is the number of times that the consumer tries to deal with a // person in the queue, but finds the queue empty int queueEmpty; // queueFull is the number of times a person tries to join the queue, but // finds it full int queueFull; // itemsProcessed is the total number of people that have joined the queue // and been dealt with int itemsProcessed; // consumer is the object that simulates the removal of people from the queue Consumer consumer; // supplier is the object that simulates the addition of people to the queue Supplier supplier; // These labels are where the values of the queue properties will be displayed // The label objects are created in the constructor Label numberInQueueLabel; Label queueLimitLabel; Label queueFullLabel; Label queueEmptyLabel; Label itemsProcessedLabel; /*============================================================================== Queue constructor Create the display elements, and the supplier and consumer objects. Then sets the supplier and consumer running. ==============================================================================*/ public Queue() { super(); // Create the consumer and supplier objects, and call // setQueue to indicate that this is the queue they // are associated with consumer = new Consumer(); consumer.setQueue(this); supplier = new Supplier(); supplier.setQueue(this); // The display for this program is very simple: it's just // ten labels arranged in a 5 x 2 grid setLayout(new GridLayout(5, 2)); add (new Label ("Number in queue")); numberInQueueLabel = new Label(""); add (numberInQueueLabel); add (new Label ("Maximum queue size")); queueLimitLabel = new Label(""); add (queueLimitLabel); add (new Label ("Items processed")); itemsProcessedLabel = new Label(""); add (itemsProcessedLabel); add (new Label ("Time queue full")); queueFullLabel = new Label(""); add (queueFullLabel); add (new Label ("Time queue empty")); queueEmptyLabel = new Label(""); add (queueEmptyLabel); // Initialize the queue parameters queueLimit = 10; numberInQueue = 0; queueEmpty = 0; queueFull = 0; // Set the labels in the display to indicate the current // queue parameters updateDisplay(); // Start the supplierand consumer running in separate threads. // From this point on the supplier and consumer run // independently of this applet supplier.start(); consumer.start(); /// QUESTION: objects of three classes are now executing independently/ /// how could we modify the program (adding only about four lines) to /// simulate the situation where people are removed from the queue /// two at a time, rather than one at a time? In other words, I want /// to represent the situation where one queue is processed by /// two different operators } /*============================================================================== stop Called by the browser when this applet should be stopped. This operation simply calls `requestStop' in the supplier and consumer. These will then stop at the next convenient point ==============================================================================*/ public void stop() { consumer.requestStop(); supplier.requestStop(); } /*============================================================================== updateDisplay Displays the values of the queue parameters in the applet. This is called whenever an item is added or removed. Although it is not particularly efficient to update all the displays every time any attribute changes, it doesn't cause any problems in this simple program ==============================================================================*/ void updateDisplay() { queueLimitLabel.setText(Integer.toString(queueLimit)); queueFullLabel.setText(Integer.toString(queueFull)); queueEmptyLabel.setText(Integer.toString(queueEmpty)); numberInQueueLabel.setText(Integer.toString(numberInQueue)); itemsProcessedLabel.setText(Integer.toString(itemsProcessed)); } /*============================================================================== supply This operation is called by the supplier object to simulate a person joining the queue. If the queue is not full, that person is accepted onto the queue, increasing its size by one. If the queue is full, its size does not increase, and the attribute which keeps a count of the number of failed queue-joining attempts is imcremented ==============================================================================*/ public void supply() { if (numberInQueue >= queueLimit) queueFull++; else numberInQueue++; updateDisplay(); } /*============================================================================== consume Called by the consumer object to indicate that it is ready to deal with the next person in the queue. If the queue is empty, then its stays empty, and we record that the queue was empty when the consumer was idle ==============================================================================*/ public void consume() { if (numberInQueue == 0) queueEmpty++; else { itemsProcessed++; numberInQueue--; } updateDisplay(); } } /*============================================================================== QueueThread class This is the base class for the supplier and consumer classes. It provides functionality that is common to both the supplier and the consumer, including the ability to wait for a random lenght of time. Because this class is a sub-class of Thread, it can be executed as a separate thread of execution, and therefore so can its sub-classes ==============================================================================*/ /// QUESTION: why is this class `abstract'? abstract class QueueThread extends Thread { // keepGoing is set to `true' initially, and is set to false when the // object should stop executing boolean keepGoing = true; // Queue is the queue object with which this supplier or consumer is // associated Queue queue; // requestStop is called when it is time for this object to stop executing, // e.g., when the applet is closed /// QUESTION: this operation sets the value of `keepGoing', but no /// operation in this class reads the value. What reads the value of /// keepGoing? public void requestStop() { keepGoing = false; } // setQueue sets the attribute that indicates the queue with which this object // is associated public void setQueue (Queue _queue) { queue = _queue; } // waitRandomTime waits for a specified random time between zero // and `milliseconds' public void waitRandomTime(int milliseconds) { int delay = (int)(Math.random() * milliseconds); try {sleep(delay);} catch(Exception e){} } } /*============================================================================== Producer and Consumer classes These are very simple in this example; they have only one operation `run'. Run is called when the applet calls `consumer.start()' or `supplier.start()' These operation continue to supply or consume people from the queue until `keepGoing' is set to false. Changing the values of `waitRandomTime' will change the simulated speed of arrivals or departures from the queue ==============================================================================*/ class Consumer extends QueueThread { public void run() { while (keepGoing) { /// QUESTION: how can this object be modified to indicate /// that people leave the queue exactly twice as fast? waitRandomTime(1000); queue.consume(); } } } class Supplier extends QueueThread { public void run() { while (keepGoing) { waitRandomTime(800); queue.supply(); } } }