Hide menu

TDDC32 Design and implementation of a software module in Java

Lab 2 - Advanced Java Programming

Your task

Your task is to write a program that implements the following producer-consumer scenario, and which has a GUI (using swing) that complies to the following descriptions.

The scenario is as follows: There are 3 producers and 3 consumers that use a bounded buffer of capacity 4 (characters).
The producers produce one character (letter) at a time, that is set in the bounded buffer if there is space available.
The consumers take one character at a time, if available, and display it.
Both the producers and the consumers are executing concurrently, hence you will need to use threads to implement this.
The bounded buffer should behave like a queue, that is, a new character is added on one end, "pushing" the other towards the opposite end. The characters are consumed (read and removed) from the end opposite to insertion.
To simulate buffer-handling, whenever a producer or a consumer gets access to the buffer, it should be delayed with a certain (common) value, that can be set from the GUI.
To simulate producing/consuming time, before/after each successful access to the buffer the producers/consumers should be delayed with a certain value (separate for the 6 threads), that can also be set from the GUI.

Remember that only one thread should be manipulating the bounded buffer at the same time, so that insertion/removal inconsistencies do not appear.

The GUI should look as follows:

  • On the left side of the GUI window you should have 3 viewports stacked on top of each other that present the activity of the producers. Each producer should have a text area where the characters already produced are displayed. In addition, each producer should have a text field that displays the status of the producer. The status can be one of the following four: "PRODUCING" - when the producer is delayed simulating production, "WAITING_ON_BUFFER_ACCESS" - when it waits to get access to the buffer, "WAITING_ON_BUFFER_NOT_FULL" - when it tried to set the value in the buffer, but the buffer was full, "MANIPULATING_BUFFER" - when it inserts in the buffer (and is delayed there).
  • On the right side of the GUI window you should have 3 viewports stacked on top of each other that present the activity of the consumers. Each consumer should have a text area where the consumed characters are displayed. In addition, each consumer should have a text field that displays the status of the consumer. The status can be one of the following four: "CONSUMING" - when the consumer is delayed simulating consumption, "WAITING_ON_BUFFER_ACCESS" - when it waits to get access to the buffer, "WAITING_ON_BUFFER_NOT_EMPTY" - when it tried to get a value from the buffer, but the buffer was empty, "MANIPULATING_BUFFER" - when it removes from the buffer (and is delayed there).
  • Both producers and consumers should have a text field or a slider where the user can insert the delay values that simulate production/consumption. To be able to differentiate between characters produced from different producers, each producer should use a different colour for their characters, i.e red for nr.1, green for nr.2 and blue for nr.3. This should be also visible in the consumer text areas.
  • In the middle of the GUI window you should present the content of the buffer (e.g. 4 boxes, with their respective characters inside, or empty). When a producer/consumer is manipulating the buffer, it's name should be displayed and the character that is added/removed should be highlighted. There should be a text field available where the user can insert the delay value that simulates buffer manipulation (which applies to all producers/consumers when they get access to the buffer). It should also be possible for the user to choose a manual manipulation mode, where he clicks on a button for allowing the current thread to exit the buffer immediately (overriding the remaining manipulation delay time).

Recommended steps

We recommend to solve the lab in the following steps:

1) First write pseudocode for the Producer/Consumer/BoundedBuffer objects where you should have all the synchronisation routines (sleep(), wait(), notify(), notifyall(), synchronized methods). Most likely you will want to have two methods in the BoundedBuffer, to be accessed by the producer and consumer.

2) Fully implement the base objects.

3) Create the GUI and connect it to the base objects.

Note: steps 2) and 3) could be implemented in parallel for better visualisation of the behaviour of your program.

Hints and Guidelines

Here follows some hints and guidelines to help you streamline the GUI development. It can be quite time-consuming to search through the Java API, so next we present some tips on how to construct the GUI. Of course, use them only if you need them.

1) A nice layout manager is BoxLayout, which lets you add components stacked either vertically or horizontally. A vertical example:
container.setLayout(newBoxLayout(container,BoxLayout.Y_AXIS));

Inside, components can be aligned horizontally or vertically, for instance a centered horizontal alignment looks like this:
component.setAlignmentX(Component.CENTER_ALIGNMENT);

For any component you can specify borders to make it clear where the boundaries are, e.g.:
component.setBorder(new LineBorder(Color.BLACK,2));

Between useful components you can insert struts so they don't appear too close to each other, e.g.:
Box.createHorisontalStrut(10);

Don't forget that for any component you can change foreground (text) and background colors and that you can hierarchically use panels to nicely layout the GUI.


2) Finding a way to display colored characters next to each other (in the consumer) can be a little bit tricky. Hence, it is OK if you don't use colors (e.g. red for producer 1, green for producer 2, and blue for producer 3), and instead display the number of the producer immediately after the character, like in "c3". This will allow you to use the JTextArea component. If you want colored output you need to use a JTextPane. Look at the following example of usage:

JTextPane txtPane = new JTextPane();
txtPane.setPreferredSize(new Dimension(300,50));
txtPane.setEditable(false);
JScrollPane sp = new JScrollPane(txtPane);
...
Document doc = txtPane.getDocument();
MutableAttributeSet ats = txtPane.getInputAttributes();
//set color:
StyleConstants.setForeground(ats, Color.GREEN); 
//append "a", in green color:
doc.insertString(doc.getEndPosition().getOffset()-1,"a",ats); 


3) About state "PRODUCING" and "MANIPULATING_BUFFER". State "PRODUCING" (and the respective delay) simulates the production, and happens before the thread wants to get access to the buffer in order to insert the value. The state "MANIPULATING_BUFFER" (and the respective delay) simulates the insertion in the buffer and happens after the thread has entered the buffer. Similarly for the consumer.

Voluntary stuff (not required)

If you feel like getting a nice exercise, put the producers and the bounded buffer on a server and the consumers on client machines and make the communication between bounded buffer and consumers to use TCP sockets.



Page responsible: Tommy Färnqvist
Last updated: 2013-01-09