Assignment 8:

Due Date: 6 April 2010 – 7:20 PM

 

Purpose:

The purpose of this assignment is to acquire understanding and experience with concurrency in the context of the Java Programming Language.

Assignment Details:

 

This assignment is composed of several small Java programs that will be utilized to explore several features of concurrency primitives support supported by the Java Programming Language:

1.       Below is a UML state diagram that shows the Java thread life cycle.

Use the following implementation and write a short implementation class called ThreadCreator that will start three PrintTask threads. Execute the PrintTask 5 times and analyze the output for the following: a) variations in task sleep time and variations in the order of tasks switching.

 1 //

 2 // PrintTask class sleeps for a random time from 0 to 5 seconds

 3 import java.util.Random;

 4

 5 public class PrintTask implements Runnable

 6 {

 7    private final int sleepTime; // random sleep time for thread

 8    private final String taskName; // name of task

 9    private final static Random generator = new Random();

10

11    public PrintTask( String name )

12    {

13       taskName = name; // set task name

14

15       // pick random sleep time between 0 and 5 seconds

16       sleepTime = generator.nextInt( 5000 ); // milliseconds

17    } // end PrintTask constructor

18

19    // method run contains the code that a thread will execute

20    public void run()

21    {

22       try // put thread to sleep for sleepTime amount of time

23       {

24          System.out.printf( "%s going to sleep for %d milliseconds.\n",

25             taskName, sleepTime );

26          Thread.sleep( sleepTime ); // put thread to sleep

27       } // end try

28       catch ( InterruptedException exception )

29       {

30          System.out.printf( "%s %s\n", taskName,

31             "terminated prematurely due to interruption" );

32       } // end catch

33

34       // print task name

35       System.out.printf( "%s done sleeping\n", taskName );

36    } // end method run

37 } // end class PrintTask

 

Below is a hint for the ThreadCreator class:

 3 import java.lang.Thread;
 4
 5 public class ThreadCreator
 6 {
 7    public static void main( String[] args )
 8    {
 9       System.out.println( "Creating threads" );
10
11       // create each thread with a new targeted runnable
12       Thread thread1 = new Thread( new PrintTask( "task1" ) );
13       
14       
15
16       System.out.println( "Threads created, starting tasks." );
17
18       // start threads and place in runnable state
19       thread1.start(); // invokes task1's run method
20       
21       
22
23       System.out.println( "Tasks started, main ends.\n" );
24    } // end main
25 } // end class RunnableTester

 

1.       The purpose of this problem is to demonstrate inserting two values into a shared array that has not been implemented with thread synchronization.  Compile and execute the Java code below and analyze the output. What did you observe on your machine with respect to this unsynchronized implementation?

 1 // 
 2 // Class that manages an integer array to be shared by multiple threads.
 3 import java.util.Random;
 4
 5 public class SimpleArray // CAUTION: NOT THREAD SAFE!
 6 {
 7    private final int array[]; // the shared integer array
 8    private int writeIndex = 0; // index of next element to be written
 9    private final static Random generator = new Random();
10
11    // construct a SimpleArray of a given size
12    public SimpleArray( int size )
13    {
14       array = new int[ size ];
15    } // end constructor
16
17    // add a value to the shared array
18    public void add( int value )
19    {
20       int position = writeIndex; // store the write index
21
22       try
23       {
24          // put thread to sleep for 0-499 milliseconds
25          Thread.sleep( generator.nextInt( 500 ) );
26       } // end try
27       catch ( InterruptedException ex )
28       {
29          ex.printStackTrace();
30       } // end catch
31
32       // put value in the appropriate element
33       array[ position ] = value;             
34       System.out.printf( "%s wrote %2d to element %d.\n",
35          Thread.currentThread().getName(), value, position );
36
37       ++writeIndex; // increment index of element to be written next
38       System.out.printf( "Next write index: %d\n", writeIndex );
39    } // end method add
40
41    // used for outputting the contents of the shared integer array
42    public String toString()
43    {
44       String arrayString = "\nContents of SimpleArray:\n";
45
46       for ( int i = 0; i < array.length; i++ )
47          arrayString += array[ i ] + " ";
48
49       return arrayString;
50    } // end method toString
51 } // end class SimpleArray

 

 1 // 
 2 // Adds integers to an array shared with other Runnables
 3 import java.lang.Runnable;
 4
 5 public class ArrayWriter implements Runnable
 6 {
 7    private final SimpleArray sharedSimpleArray;
 8    private final int startValue;
 9
10    public ArrayWriter( int value, SimpleArray array )
11    {
12       startValue = value;
13       sharedSimpleArray = array;
14    } // end constructor
15
16     public void run()
17    {
18       for ( int i = startValue; i < startValue + 3; i++ )
19       {
20          sharedSimpleArray.add( i ); // add an element to the shared array
21       } // end for
22    } // end method run
23 } // end class ArrayWriter

 

 1 // 
 2 // Executes two Runnables to add elements to a shared SimpleArray.
 3 import java.util.concurrent.Executors;
 4 import java.util.concurrent.ExecutorService;
 5 import java.util.concurrent.TimeUnit;
 6
 7 public class SharedArrayTest
 8 {
 9    public static void main( String[] arg )
10    {
11       // construct the shared object
12       SimpleArray sharedSimpleArray = new SimpleArray( 6 );
13
14       // create two tasks to write to the shared SimpleArray
15       ArrayWriter writer1 = new ArrayWriter( 1, sharedSimpleArray );
16       ArrayWriter writer2 = new ArrayWriter( 11, sharedSimpleArray );
17
18       // execute the tasks with an ExecutorService
19       ExecutorService executor = Executors.newCachedThreadPool();
20       executor.execute( writer1 );
21       executor.execute( writer2 );
22
23       executor.shutdown();
24
25       try
26       {
27          // wait 1 minute for both writers to finish executing
28          boolean tasksEnded = executor.awaitTermination(
29             1, TimeUnit.MINUTES );
30
31          if ( tasksEnded )
32             System.out.println( sharedSimpleArray ); // print contents
33          else
34             System.out.println(
35                "Timed out while waiting  for tasks to finish." );
36       } // end try
37       catch ( InterruptedException ex )
38       {
39          System.out.println(
40             "Interrupted while wait for tasks to finish." );
41       } // end catch
42    } // end main
43 } // end class SharedArrayTest

 

2.       Modify the code in problem two to be synchronized. Hint: only one line in the SimpleArray class need to be modified to convert problem two for synchronization. HintHint: inspect the add method in the SimpleArray class as a potential candidate for synchronization. Compare the output against problem 2.