This is an old version of this course, from Winter 2014-2015. A newer version is avaliable here.
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 it's libraries (e.g. JCF and Swing) is full of warnings regarding various methods being "not thread-safe", meaning that incorporation of thread-safety is up to you, the user of the libraries.
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.
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, and it's contents, to the console.
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.
(Comment added 24-Jan-2015) In each example explain the specific cause of the crash (if it does), and why the numbers come out the way they do.
Demonstrate this to your instructor before proceeding. (If the instructor is not available, continue to the next part, but be ready to demo this part when needed.)
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.
Demonstrate this to your instructor before proceeding.
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.
Demonstrate this to your instructor before proceeding.
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
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, such that each thread takes 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. 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 Monitor 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.
Lab Report
You must create a simple 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. Be sure to include a well-reasoned summary explanation of the various behaviors you observed.
Acknowledgement
This lab developed by MSOE faculty.