SE2811
Software Component Design

SE2811 Lab: Thread-safe Collections

In this assignment, you will learn how to access a Java Collections Framework (JCF) Collection in a thread-safe manner by using various thread synchronization techniques that are part of the Java language.

Assignment Overview

Using multiple threads of execution is a powerful design paradigm that has many benefits when implemented correctly; for example, a well-designed applications can be much more responsive to user input even while carrying out complex activities in the background. On the downside, improper implementation of multi-threading can introduce unpredictable behavior due to insidious errors that can be difficult to detect. This is especially true when portions of the same code are executed on multiple threads. Sun's Javadoc for many of its libraries (e.g. JCF and Swing) is full of warnings regarding various methods being "not thread-safe." This means steps must be take by developers to synchronize access when used in multi-threaded applications.

Report Template

As you work through this lab, fill in your findings in the report template. At the top of the template, fill in your name and the date. Under each section heading, write any text or example output for each section. Please keep example output brief, and put a blank line between paragraphs.

Directions on submitting the report are given below.

Assignment details

Part 1

Begin by creating an application that implements the following class:

This code should be created in the package <name>.part1 where <name> is your MSOE username.

Within this application, the main() method instantiates an instance of the JCFAccessApp class. Within the constructor, a secondary thread is to be created that executes the addElements() method. Immediately following the creation of the secondary thread, the addElements() method should be invoked (on the primary thread). This is illustrated in the following UML Activity diagram. When the addElements() methods complete, join() the secondary thread to the primary thread and output the size of the Collection with its contents to the console. Print each element of the collection on its own line.

Within the addElements() method, implement a for() loop that adds a number of integer elements to the Collection as specified by the count argument. (e.g. for this lab, specify a value for count of 10,000 in order to add the values 1 through 10,000 to the Collection). Note that the Collection is declared as a List but is shown in the class diagram as an ArrayList.

Run the application several times. Note that it may crash, but does it always crash? Why do you think it crashes? What is the result when it doesn't crash? Is it what you expect? What is happening? Copy the output of the console to your report (described below), and record your observations. Note: it is not necessary to copy the entire console output (with thousands of values) to your report; just present a portion that is representative of the "interesting" behavior. Be sure to label and document each of the outputs. For those with crashes, give an explanation of the cause of the crash and why the numbers appear as they do.

Part 2

Create a new package <name>.part2. Copy the code from part 1 into this package and then modify your code such that a LinkedList is used instead of an ArrayList. Run the application again several times - the behavior will differ from run to run. Copy the "interesting" console output to your report and record your observations. Explain what you think is happening.

Part 3

Create a new package <name>.part3. Copy the code from part 2 into this package. Modify the addElements() method, declaring the method synchronized. Run the application again several times. Copy the console output to your report and record your observations, specifically noting differences in behavior.

Part 4

Create a new package <name>.part4. Copy the code from part 3 into this package. Remove the synchronized specifier from the addElements() method. This time, implement a synchronized block within the addElements() method around the JCF method calls, making only access to the Collection synchronized. Run the application again several times. Copy the console output to your report and record your observations.

Demonstrate this to your instructor before proceeding.

Part 5

Create a new package <name>.part5. Copy the code from part 2 into this package. Modify your code such that the instantiation of the LinkedList is passed through the Collections.synchronizedList() method before being assigned to the List alist. Run the application again several times. Copy the "interesting" console output to your report and record your observations. Read the JavaDoc for the Collections class and explain why the behavior differs from that seen in Part 1 and Part 2.

Part 6

As may have been discussed in class, calling notify() in a synchronized block followed by wait() results in running the other threads waiting at the block before returning to the current thread. This does not change how synchronized code works - it's still true that only one thread is running in it at a time - but it allows the different threads to "interleave" their work.

Some gotcha's of notify and wait: These are methods of the Object class, so any object x can be used to call x.notify() or x.wait(). The x could be the thread object, a String, a List, or even a class object like Bee.class. However, these methods can only be called if x is locked. That is, if you write synchronized(x) { ... }, then be sure that the notify and wait operations are applied to that same object x: x.notify() and x.wait(...), and only inside the synchronized block.

For this part, create a new package <name>.part6. Copy the code from part 4 into this package. Within the synchronized block, add notify() and wait() methods so that the two threads run interleaved. The result is that each thread will take a single turn at adding an element to the Collection before allowing the other thread to do the same. Run the application again several times. Copy the console output to your report and record your observations.

Part 7

This part is optional and rather complex, but required to get an 'A' grade. If you choose not to do it, the maximum grade you will receive is 'AB'.

Create a new package <name>.part7. Copy the code from part 6 into this package. In this part, we rotate numbers through the list, adding the numbers with the add method, and removing them with a new removeElements() method. Add a removeElements() method to the class, which, on the primary thread, repeatedly removes elements from the FRONT of the list once the list has had at least 10 elements added to it by the addElements() method running on the secondary thread. Within the repetition, use a synchronized block that uses the same synchronization object as the addElements() method to control access to the removal of elements. The net effect should be that the two threads run interleaved, such that the thread running addElements() takes a single turn at adding an element (once it has added the first 10 elements) to the Collection before allowing the other thread running removeElements() to remove an element. Run the application again several times. Copy the console output to your report and record your observations. Hint: To implement this, have the removeElements() method, when it begins executing, enter a synchronized block that starts the secondary thread (which runs addElements()) and then waits for a notify from addElements() indicating that it is ok to start removing elements from the front of the list. That notification is only issued by addElements() when it has added 10 elements to the list. Once that initial synchronization is performed, the two threads can then start cooperatively interleaving their respective operations. Ask for help if you're not sure what this means!

Lab Report

As discussed above, create a lab report for this assignment. Within the report, present the data and information you gather from each part of the assignment above. Format the data neatly and make your comments clear and understandable. The report will be graded for grammar and spelling as well as content. Be sure to include a well-reasoned summary explanation of the various behaviors you observed.

Demonstrate your final implementation to your instructor. Complete the demonstration by Wednesday of week 4.

Acknowledgement

This lab developed by MSOE faculty.

Submission Form for Dr. Yoder