Transcript jhtp5_16

Chapter 16 – Multithreading
Outline
16.1
16.2
16.3
16.4
16.5
16.6
16.7
16.8
16.9
16.10
16.11
16.12
Introduction
Thread States: Life Cycle of a Thread
Thread Priorities and Thread Scheduling
Creating and Executing Threads
Thread Synchronization
Producer/Consumer Relationship without Synchronization
Producer/Consumer Relationship with Synchronization
Producer/Consumer Relationship: Circular Buffer
Daemon Threads
Runnable Interface
(Optional Case Study) Thinking About Objects:
Multithreading
(Optional) Discovering Design Patterns: Concurrent Design
Patterns
 2003 Prentice Hall, Inc. All rights reserved.
16.1 Introduction
• Concurrency normally available in OS primitives
• Java provides built-in multithreading
– Multithreading improves the performance of some programs
 2003 Prentice Hall, Inc. All rights reserved.
16.2 Thread States: Life Cycle of a Thread
• Thread states
– Born state
• Thread was just created
– Ready state
• Thread’s start method invoked
• Thread can now execute
– Running state
• Thread is assigned a processor and running
– Dead state
• Thread has completed or exited
• Eventually disposed of by system
 2003 Prentice Hall, Inc. All rights reserved.
Fig. 16.1 Thread life-cycle statechart diagram
Born
start
quantum expiration
yield
Waiting
sleep interval
expires
interrupt
 2003 Prentice Hall, Inc. All rights reserved.
thread dispatch
(assign a
processor)
I/O completes
acquire lock
interrupt
notify
notifyAll
timeout expires
interrupt
Ready
Running
Sleeping
Blocked
When a thread completes
(returns from its run method),
it reaches the Dead state
(shown here as the final state)
16.3 Thread Priorities and Thread
Scheduling
• Java thread priority
– Priority in range 1-10
• Timeslicing
– Each thread assigned time on the processor (called a
quantum)
– Keeps highest priority threads running
 2003 Prentice Hall, Inc. All rights reserved.
Fig. 16.2 Thread priority scheduling example
Ready threads
Thread.MAX_PRIORITY
Priority 10
A
Priority 9
C
B
Priority 8
Thread.NORM_PRIORITY
Priority 7
D
E
Priority 6
G
Priority 5
H
I
J
K
Priority 4
Priority 3
Priority 2
Thread.MIN_PRIORITY
 2003 Prentice Hall, Inc. All rights reserved.
Priority 1
F
16.4 Creating and Executing Threads
• Sleep state
– Thread method sleep called
– Thread sleeps for a set time interval then awakens
 2003 Prentice Hall, Inc. All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Fig. 16.3: ThreadTester.java
// Multiple threads printing at different intervals.
public class ThreadTester {
public static void main( String [] args )
{
// create and name each thread
PrintThread thread1 = new PrintThread( "thread1" );
PrintThread thread2 = new PrintThread( "thread2" );
PrintThread thread3 = new PrintThread( "thread3" );
Outline
ThreadTester.ja
va
Lines 9-11
create four
Lines
15-17
PrintThreads
System.err.println( "Starting threads" );
thread1.start(); // start thread1 and place it in ready state
thread2.start(); // start thread2 and place it in ready state
thread3.start(); // start thread3 and place it in ready state
call start methods
System.err.println( "Threads started, main ends\n" );
} // end main
} // end class ThreadTester
 2003 Prentice Hall, Inc.
All rights reserved.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// class PrintThread controls thread execution
class PrintThread extends Thread {
private int sleepTime;
// assign name to thread by calling superclass constructor
public PrintThread( String name )
{
super( name );
// pick random sleep time between 0 and 5 seconds
sleepTime = ( int ) ( Math.random() * 5001 );
}
// method run is the code to be executed by new thread
public void run()
{
// put thread to sleep for sleepTime amount of time
try {
System.err.println(
getName() + " going to sleep for " + sleepTime );
Outline
ThreadTester.ja
PrintThread
va
extends Thread
Line 26
Line 35
Constructor
initializes
Line 39
sleepTime
When the thread
enters the running
state, run is called
Thread.sleep( sleepTime );
}
 2003 Prentice Hall, Inc.
All rights reserved.
49
50
51
52
53
54
55
56
57
58
59
// if thread interrupted during sleep, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
// print thread name
System.err.println( getName() + " done sleeping" );
Outline
ThreadTester.ja
va
} // end method run
} // end class PrintThread
Starting threads
Threads started, main ends
thread1
thread2
thread3
thread3
thread1
thread2
going to sleep for 1217
going to sleep for 3989
going to sleep for 662
done sleeping
done sleeping
done sleeping
 2003 Prentice Hall, Inc.
All rights reserved.
Starting threads
thread1 going to sleep for 314
thread2 going to sleep for 1990
Threads started, main ends
thread3
thread1
thread2
thread3
Outline
ThreadTester.ja
va
going to sleep for 3016
done sleeping
done sleeping
done sleeping
 2003 Prentice Hall, Inc.
All rights reserved.
16.5 Thread Synchronization
• Java uses monitors for thread synchronization
• The sychronized keyword
–
–
–
–
Every synchronized method of an object has a monitor
One thread inside a synchronized method at a time
All other threads block until method finishes
Next highest priority thread runs when method finishes
 2003 Prentice Hall, Inc. All rights reserved.
16.6 Producer/Consumer Relationship
without Synchronization
• Buffer
– Shared memory region
• Producer thread
– Generates data to add to buffer
– Calls wait if consumer has not read previous message in
buffer
– Writes to empty buffer and calls notify for consumer
• Consumer thread
– Reads data from buffer
– Calls wait if buffer empty
• Synchronize threads to avoid corrupted data
 2003 Prentice Hall, Inc. All rights reserved.
1
2
3
4
5
6
7
// Fig. 16.4: Buffer.java
// Buffer interface specifies methods called by Producer and Consumer.
public interface Buffer {
public void set( int value );
public int get();
}
// place value into Buffer
// return value from Buffer
Outline
Buffer.java
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Fig. 16.5: Producer.java
// Producer's run method controls a thread that
// stores values from 1 to 4 in sharedLocation.
public class Producer extends Thread {
private Buffer sharedLocation; // reference to shared object
// constructor
public Producer( Buffer shared )
{
super( "Producer" );
sharedLocation = shared;
}
Outline
Producer
Producer.java
extends
Thread
Line 5
This is a shared object
Line 6
Line 16
Lines 22-23
// store values from 1 to 4 in sharedLocation
public void run()
{
for ( int count = 1; count <= 4; count++ ) {
// sleep 0 to 3 seconds, then place value in Buffer
try {
Thread.sleep( ( int ) ( Math.random() * 3001 ) );
sharedLocation.set( count );
}
Method run is overridden
The thread goes to sleep,
then the buffer is set
 2003 Prentice Hall, Inc.
All rights reserved.
26
27
28
29
30
31
32
33
34
35
36
37
38
// if sleeping thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
Outline
Producer.java
} // end for
System.err.println( getName() + " done producing." +
"\nTerminating " + getName() + ".");
} // end method run
} // end class Producer
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Fig. 16.6: Consumer.java
// Consumer's run method controls a thread that loops four
// times and reads a value from sharedLocation each time.
public class Consumer extends Thread {
private Buffer sharedLocation; // reference to shared object
// constructor
public Consumer( Buffer shared )
{
super( "Consumer" );
sharedLocation = shared;
}
Outline
Consumer
Consumer.java
extends
Thread
Line 5
This is a shared object
Line 6
Line 16
Lines 24-25
// read sharedLocation's value four times and sum the values
public void run()
{
int sum = 0;
Method run is overridden
for ( int count = 1; count <= 4; count++ ) {
// sleep 0 to 3 seconds, read value from Buffer and add to sum
try {
Thread.sleep( ( int ) ( Math.random() * 3001 ) );
sum += sharedLocation.get();
}
The thread goes to sleep,
then the buffer is read
 2003 Prentice Hall, Inc.
All rights reserved.
28
29
30
31
32
33
34
35
36
37
38
39
// if sleeping thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
}
Outline
Consumer.java
System.err.println( getName() + " read values totaling: " + sum +
".\nTerminating " + getName() + ".");
} // end method run
} // end class Consumer
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Outline
// Fig. 16.7: UnsynchronizedBuffer.java
// UnsynchronizedBuffer represents a single shared integer.
This class implements the
UnsynchronizedB
Buffer interface
uffer.java
public class UnsynchronizedBuffer implements Buffer {
private int buffer = -1; // shared by producer and consumer threads
// place value into buffer
public void set( int value )
{
System.err.println( Thread.currentThread().getName() +
" writes " + value );
buffer = value;
The data is a single
Line 4integer
This method sets
Linethe
5 value
in the buffer
Lines 8 and 13
}
// return value from buffer
public int get()
{
System.err.println( Thread.currentThread().getName() +
" reads " + buffer );
Lines 17 and 22
This method reads the
value in the buffer
return buffer;
}
} // end class UnsynchronizedBuffer
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Fig. 16.8: SharedBufferTest.java
// SharedBufferTest creates producer and consumer threads.
public class SharedBufferTest {
public static void main( String [] args )
{
// create shared object used by threads
Buffer sharedLocation = new UnsynchronizedBuffer();
// create producer and consumer objects
Producer producer = new Producer( sharedLocation );
Consumer consumer = new Consumer( sharedLocation );
producer.start();
consumer.start();
// start producer thread
// start consumer thread
Outline
SharedBufferTes
t.java
Line 9
Create a Buffer object
Lines 12-13
Create a Producer and
Lines 15-16
a Consumer
Start the Producer and
Consumer threads
} // end main
} // end class SharedCell
 2003 Prentice Hall, Inc.
All rights reserved.
Consumer reads -1
Producer writes 1
Consumer reads 1
Consumer reads 1
Consumer reads 1
Consumer read values totaling: 2.
Terminating Consumer.
Producer writes 2
Producer writes 3
Producer writes 4
Producer done producing.
Terminating Producer.
Outline
SharedBufferTes
t.java
Producer writes 1
Producer writes 2
Consumer reads 2
Producer writes 3
Consumer reads 3
Producer writes 4
Producer done producing.
Terminating Producer.
Consumer reads 4
Consumer reads 4
Consumer read values totaling: 13.
Terminating Consumer.
 2003 Prentice Hall, Inc.
All rights reserved.
Producer writes 1
Consumer reads 1
Producer writes 2
Consumer reads 2
Producer writes 3
Consumer reads 3
Producer writes 4
Producer done producing.
Terminating Producer.
Consumer reads 4
Consumer read values totaling: 10.
Terminating Consumer.
Outline
SharedBufferTes
t.java
 2003 Prentice Hall, Inc.
All rights reserved.
16.7 Producer/Consumer Relationship with
Synchronization
• Synchronize threads to ensure correct data
 2003 Prentice Hall, Inc. All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
This class implements
// Fig. 16.9: SynchronizedBuffer.java
// SynchronizedBuffer synchronizes access to a single shared integer. Buffer interface
the
Outline
public class SynchronizedBuffer implements Buffer {
private int buffer = -1; // shared by producer and consumer threads
Remember
private int occupiedBufferCount = 0; // count of occupied buffers
SynchronizedBuf
the number
of
fer.java
filled spaces
Line 4
Method set is declared
synchronized
Line 6
// place value into buffer
public synchronized void set( int value )
{
// for output purposes, get name of thread that called this method
String name = Thread.currentThread().getName();
Get the
name of the thread
Line 9
// while there are no empty locations, place thread in waiting state
while ( occupiedBufferCount == 1 ) {
// output thread information and buffer information, then wait
Wait while
try {
System.err.println( name + " tries to write." );
displayState( "Buffer full. " + name + " waits." );
wait();
}
Line 12
and 21
the Lines
buffer15
is filled
// if waiting thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
 2003 Prentice Hall, Inc.
All rights reserved.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
} // end while
buffer = value; // set new buffer value
// indicate producer cannot store another value
// until consumer retrieves current buffer value
++occupiedBufferCount;
displayState( name + " writes " + buffer );
notify(); // tell waiting thread to enter ready state
Outline
Write to the buffer
SynchronizedBuf
fer.java
Line 31
Increment the buffer
count
Line 35
Alert a waiting thread
Line 39
} // end method set; releases lock on SynchronizedBuffer
Line 44
// return value from buffer
Method get is declared
public synchronized int get()
Line 47
synchronized
{
// for output purposes, get name of thread that called this method
String name = Thread.currentThread().getName();
Get the name of the thread
 2003 Prentice Hall, Inc.
All rights reserved.
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
Outline
// while no data to read, place thread in waiting state
while ( occupiedBufferCount == 0 ) {
// output thread information and buffer information, then wait
Wait while
try {
System.err.println( name + " tries to read." );
displayState( "Buffer empty. " + name + " waits." );
wait();
}
// if waiting thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
} // end while
// indicate that producer can store another value
// because consumer just retrieved buffer value
--occupiedBufferCount;
SynchronizedBuf
the buffer is empty
fer.java
Lines 50 and 56
Line 68
Line 72
Line 74
Decrement the buffer count
displayState( name + " reads " + buffer );
notify(); // tell waiting thread to become ready to execute
return buffer;
Alert a waiting thread
Return the buffer
 2003 Prentice Hall, Inc.
All rights reserved.
75
76
77
78
79
80
81
82
83
84
85
86
87
88
} // end method get; releases lock on SynchronizedBuffer
// display current operation and buffer state
public void displayState( String operation )
{
StringBuffer outputLine = new StringBuffer( operation );
outputLine.setLength( 40 );
outputLine.append( buffer + "\t\t" + occupiedBufferCount );
System.err.println( outputLine );
System.err.println();
}
Outline
SynchronizedBuf
fer.java
} // end class SynchronizedBuffer
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Outline
// Fig. 16.10: SharedBufferTest2.java
// SharedBufferTest2creates producer and consumer threads.
public class SharedBufferTest2 {
SharedBufferTes
t2.java
Create a Buffer object
Line 11
SynchronizedBuffer
public static void main( String [] args )
{
// create shared object used by threads; we use a
// reference rather than a Buffer reference so we can invoke
// SynchronizedBuffer method displayState from main
SynchronizedBuffer sharedLocation = new SynchronizedBuffer();
// Display column heads for output
StringBuffer columnHeads = new StringBuffer( "Operation" );
columnHeads.setLength( 40 );
columnHeads.append( "Buffer\t\tOccupied Count" );
System.err.println( columnHeads );
System.err.println();
sharedLocation.displayState( "Initial State" );
// create producer and consumer objects
Producer producer = new Producer( sharedLocation );
Consumer consumer = new Consumer( sharedLocation );
Line 19
Lines 22-23
Output initial state
Create a Producer and
a Consumer
 2003 Prentice Hall, Inc.
All rights reserved.
25
26
27
28
29
30
producer.start();
consumer.start();
Outline
// start producer thread
// start consumer thread
Start the Producer and
Consumer threads
SharedBufferTes
t2.java
} // end main
} // end class SharedBufferTest2
Lines 25-26
Operation
Buffer
Occupied Count
Initial State
-1
0
Buffer empty. Consumer waits.
-1
0
Producer writes 1
1
1
Consumer reads 1
1
0
Consumer tries to read.
Buffer empty. Consumer waits.
1
0
Producer writes 2
2
1
Consumer reads 2
2
0
Producer writes 3
3
1
Consumer tries to read.
 2003 Prentice Hall, Inc.
All rights reserved.
Consumer reads 3
3
0
Consumer tries to read.
Buffer empty. Consumer waits.
3
0
Producer writes 4
4
1
Consumer reads 4
Producer done producing.
Terminating Producer.
4
0
Operation
Buffer
Occupied Count
Initial State
-1
0
Consumer tries to read.
Buffer empty. Consumer waits.
-1
0
Producer writes 1
1
1
Consumer reads 1
1
0
Producer writes 2
2
1
Outline
SharedBufferTes
t2.java
Consumer read values totaling: 10.
Terminating Consumer.
 2003 Prentice Hall, Inc.
All rights reserved.
Producer tries to write.
Buffer full. Producer waits.
2
1
Consumer reads 2
2
0
Producer writes 3
3
1
Consumer reads 3
3
0
Producer writes 4
4
1
Producer done producing.
Terminating Producer.
Consumer reads 4
4
0
Outline
SharedBufferTes
t2.java
Consumer read values totaling: 10.
Terminating Consumer.
Operation
Buffer
Occupied Count
Initial State
-1
0
Producer writes 1
1
1
Consumer reads 1
1
0
Producer writes 2
2
1
 2003 Prentice Hall, Inc.
All rights reserved.
Consumer reads 2
2
0
Producer writes 3
3
1
Consumer reads 3
3
0
Producer writes 4
4
1
Producer done producing.
Terminating Producer.
Consumer reads 4
4
0
Outline
SharedBufferTes
t2.java
Consumer read values totaling: 10.
Terminating Consumer.
 2003 Prentice Hall, Inc.
All rights reserved.
16.8 Producer/Consumer Relationship:
Circular Buffer
• Circular buffer
– Multiple memory cells
– Produce item if one or more empty cells
– Consume item if one or more filled cells
 2003 Prentice Hall, Inc. All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Outline
// Fig. 16.11: RunnableOutput.java
// Class RunnableOutput updates JTextArea with output
import javax.swing.*;
public class RunnableOutput implements Runnable {
private JTextArea outputArea;
private String messageToAppend;
RunnableOutput.
This class implements
the
java
Runnable interface
Line 5
// initialize outputArea and message
public RunnableOutput( JTextArea output, String message )
{
outputArea = output;
messageToAppend = message;
}
// method called by SwingUtilities.invokeLater to update outputArea
public void run()
{
outputArea.append( messageToAppend );
}
Line 17
Declare method run
} // end class RunnableOutput
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Fig. 16.12: Producer.java
// Producer’s run method controls a thread that
// stores values from 11 to 20 in sharedLocation.
import javax.swing.*;
public class Producer extends Thread {
private Buffer sharedLocation;
private JTextArea outputArea;
Outline
Producer.java
Lines 21 and 26
// constructor
public Producer( Buffer shared, JTextArea output )
{
super( "Producer" );
sharedLocation = shared;
outputArea = output;
}
// store values from 11-20 and in sharedLocation's buffer
public void run()
{
for ( int count = 11; count <= 20; count ++ ) {
// sleep 0 to 3 seconds, then place value in Buffer
try {
Thread.sleep( ( int ) ( Math.random() * 3000 ) );
sharedLocation.set( count );
}
Write the values from 11 to
20 to the buffer
 2003 Prentice Hall, Inc.
All rights reserved.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// if sleeping thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
}
Outline
Producer.java
Lines 36-37
String name = getName();
SwingUtilities.invokeLater( new RunnableOutput( outputArea, "\n" +
name + " done producing.\n" + name + " terminated.\n" ) );
} // end method run
} // end class Producer
Update the output
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Fig. 16.13: Consumer.java
// Consumer’s run method controls a thread that loops ten
// times and reads a value from sharedLocation each time.
import javax.swing.*;
Outline
Consumer.java
public class Consumer extends Thread {
private Buffer sharedLocation; // reference to shared object
private JTextArea outputArea;
// constructor
public Consumer( Buffer shared, JTextArea output )
{
super( "Consumer" );
sharedLocation = shared;
outputArea = output;
}
// read sharedLocation's value ten times and sum the values
public void run()
{
int sum = 0;
for ( int count = 1; count <= 10; count++ ) {
 2003 Prentice Hall, Inc.
All rights reserved.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// sleep 0 to 3 seconds, read value from Buffer and add to sum
try {
Thread.sleep( ( int ) ( Math.random() * 3001 ) );
sum += sharedLocation.get();
}
// if sleeping thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
Outline
Read the value
Consumer.java
from the buffer
Line 28
Lines 38-40
}
String name = getName();
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\nTotal " + name + " consumed: " + sum + ".\n" +
name + " terminated.\n ") );
} // end method run
} // end class Consumer
Update the output
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Fig. 16.14: CircularBuffer.java
// CircularBuffer synchronizes access to an array of shared buffers.
import javax.swing.*;
public class CircularBuffer implements Buffer {
// each array element is a buffer
private int buffers[] = { -1, -1, -1 };
// occupiedBufferCount maintains count of occupied buffers
private int occupiedBufferCount = 0;
// variables that maintain read and write buffer locations
private int readLocation = 0, writeLocation = 0;
Outline
CircularBuffer.
java
The data is an array of
Line 8
three integers
Remember the number
Line 11 of
filled spaces
Line 14
Remember the read and
write positions
// reference to GUI component that displays output
private JTextArea outputArea;
// constructor
public CircularBuffer( JTextArea output )
{
outputArea = output;
}
 2003 Prentice Hall, Inc.
All rights reserved.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Outline
// place value into buffer
Method set is declared
public synchronized void set( int value )
synchronized
{
// for output purposes, get name of thread that called this method
CircularBuffer.
String name = Thread.currentThread().getName();
java
// while there are no empty locations, place thread in waiting state
while ( occupiedBufferCount == buffers.length ) {
Check
// output thread information and buffer information, then wait
try {
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\nAll buffers full. " + name + " waits." ) );
wait();
}
// if waiting thread interrupted, print stack trace
catch ( InterruptedException exception )
{
exception.printStackTrace();
}
Line
26 is full
if the
buffer
Line 32
Lines 36-37
Line 50
Update the output
} // end while
// place value in writeLocation of buffers
buffers[ writeLocation ] = value;
Write to the buffer
 2003 Prentice Hall, Inc.
All rights reserved.
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
Outline
// update Swing GUI component with produced value
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\n" + name + " writes " + buffers[ writeLocation ] + " ") );
// just produced a value, so increment number of occupied
++occupiedBufferCount;
// update writeLocation for future write operation
writeLocation = ( writeLocation + 1 ) % buffers.length;
// display contents of shared buffers
SwingUtilities.invokeLater( new RunnableOutput(
outputArea, createStateOutput() ) );
Update the output
CircularBuffer.
buffers
Increment thejava
buffer count
Lines 53-54
Update the write location
Line 57
notify(); // return waiting thread (if there is one) to ready state
} // end method set
Update the output
Line 60
Alert aLines
waiting
thread
63-64
Line 66
// return value from buffer
Method get is declared
public synchronized int get()
Line 71
synchronized
{
// for output purposes, get name of thread that called this method
String name = Thread.currentThread().getName();
 2003 Prentice Hall, Inc.
All rights reserved.
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// while no data to read, place thread in waiting state
while ( occupiedBufferCount == 0 ) {
Outline
Check if the buffer is empty
// output thread information and buffer information, then wait
try {
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\nAll buffers empty. " + name + " waits.") );
wait();
}
// if waiting thread interrupted, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
CircularBuffer.
java
Line 77
Lines 81-82
Update the output
Line 94
Lines 97-98
} // end while
// obtain value at current readLocation
int readValue = buffers[ readLocation ];
// update Swing GUI component with consumed value
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
"\n" + name + " reads " + readValue + " ") );
Line 101
Read a value from the buffer
Update the output
// just consumed a value, so decrement number of occupied buffers
--occupiedBufferCount;
Decrement
the buffer count
 2003 Prentice Hall, Inc.
All rights reserved.
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
Outline
// update readLocation for future read operation
readLocation = ( readLocation + 1 ) % buffers.length;
Update the read location
// display contents of shared buffers
SwingUtilities.invokeLater( new RunnableOutput(
outputArea, createStateOutput() ) );
CircularBuffer.
Update
the output
java
notify(); // return waiting thread (if there is one) to ready state
104 thread
Alert aLine
waiting
return readValue;
Return a valueLines
from 107-108
the buffer
} // end method get
Line 110
// create state output
public String createStateOutput()
{
// first line of state information
String output =
"(buffers occupied: " + occupiedBufferCount + ")\nbuffers: ";
Line 112
for ( int i = 0; i < buffers.length; i++ )
output += " " + buffers[ i ] + " ";
// second line of state information
output += "\n
";
 2003 Prentice Hall, Inc.
All rights reserved.
129
for ( int i = 0; i < buffers.length; i++ )
130
output += "---- ";
131
132
// third line of state information
133
output += "\n
";
134
135
// append readLocation (R) and writeLocation (W)
136
// indicators below appropriate buffer locations
137
for ( int i = 0; i < buffers.length; i++ )
138
139
if ( i == writeLocation && writeLocation == readLocation )
140
output += " WR ";
141
else if ( i == writeLocation )
142
output += " W
";
143
else if ( i == readLocation )
144
output += " R ";
145
else
146
output += "
";
147
148
output += "\n";
149
150
return output;
151
152
} // end method createStateOutput
153
154 } // end class CircularBuffer
Outline
CircularBuffer.
java
 2003 Prentice Hall, Inc.
All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Fig. 16.15: CircularBufferTest.java
// CircularBufferTest shows two threads manipulating a circular buffer.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// set up the producer and consumer threads and start them
public class CircularBufferTest extends JFrame {
JTextArea outputArea;
Outline
CircularBufferT
est.java
Line 26
// set up GUI
public CircularBufferTest()
{
super( "Demonstrating Thread Synchronizaton" );
outputArea = new JTextArea( 20,30 );
outputArea.setFont( new Font( "Monospaced", Font.PLAIN, 12 ) );
getContentPane().add( new JScrollPane( outputArea ) );
setSize( 310, 500 );
setVisible( true );
Create a Buffer object
// create shared object used by threads; we use a CircularBuffer
// reference rather than a Buffer reference so we can invoke
// CircularBuffer method createStateOutput
CircularBuffer sharedLocation = new CircularBuffer( outputArea );
 2003 Prentice Hall, Inc.
All rights reserved.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// display initial state of buffers in CircularBuffer
SwingUtilities.invokeLater( new RunnableOutput( outputArea,
sharedLocation.createStateOutput() ) );
// set up threads
Producer producer = new Producer( sharedLocation, outputArea );
Consumer consumer = new Consumer( sharedLocation, outputArea );
producer.start();
consumer.start();
// start producer thread
// start consumer thread
Outline
Update the output
CircularBufferT
est.java
Create
a Producer and
a Consumer
Lines 29-30
Start the Producer and
Consumer
threads
Lines 33-34
} // end constructor
Lines 36-37
public static void main ( String args[] )
{
CircularBufferTest application = new CircularBufferTest();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
Line
Create
an 43
instance of this
class
} // end class CirclularBufferTest
 2003 Prentice Hall, Inc.
All rights reserved.
Outline
CircularBufferT
est.java
Value placed in last
buffer. Next value will be
deposited in first buffer.
 2003 Prentice Hall, Inc.
All rights reserved.
Outline
CircularBufferT
est.java
Circular buffer effect—the
fourth value is deposited
in the first buffer.
Value placed in last buffer.
Next value will be
deposited in first buffer.
Circular buffer effect—the
seventh value is deposited
in the first buffer.
 2003 Prentice Hall, Inc.
All rights reserved.
Outline
CircularBufferT
est.java
Value placed in last buffer.
Next value will be
deposited in first buffer.
Circular buffer effect—the
tenth value is deposited in
the first buffer.
 2003 Prentice Hall, Inc.
All rights reserved.
Outline
CircularBufferT
est.java
 2003 Prentice Hall, Inc.
All rights reserved.
16.9 Daemon Threads
• Run for benefit of other threads
– Do not prevent program from terminating
– Garbage collector is a daemon thread
• Set daemon thread with method setDaemon
 2003 Prentice Hall, Inc. All rights reserved.
16.10 Runnable Interface
• A class cannot extend more than one class
• Implement Runnable for multithreading support
 2003 Prentice Hall, Inc. All rights reserved.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Fig. 16.16: RandomCharacters.java
// Class RandomCharacters demonstrates the Runnable interface
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
Outline
RandomCharacter
s.java
public class RandomCharacters extends JApplet implements ActionListener {
private String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private final static int SIZE = 3;
private JLabel outputs[];
private JCheckBox checkboxes[];
private Thread threads[];
private boolean suspended[];
// set up GUI and arrays
public void init()
{
outputs = new JLabel[ SIZE ];
checkboxes = new JCheckBox[ SIZE ];
threads = new Thread[ SIZE ];
suspended = new boolean[ SIZE ];
Container container = getContentPane();
container.setLayout( new GridLayout( SIZE, 2, 5, 5 ) );
 2003 Prentice Hall, Inc.
All rights reserved.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Outline
// create GUI components, register listeners and attach
// components to content pane
for ( int count = 0; count < SIZE; count++ ) {
outputs[ count ] = new JLabel();
outputs[ count ].setBackground( Color.GREEN );
outputs[ count ].setOpaque( true );
container.add( outputs[ count ] );
RandomCharacter
s.java
Line 43
checkboxes[ count ] = new JCheckBox( "Suspended" );
checkboxes[ count ].addActionListener( this );
container.add( checkboxes[ count ] );
Lines 48-49
}
Applet
start51method
Line
} // end method init
// create and start threads each time start is called (i.e., after
// init and when user revists Web page containing this applet)
public void start()
{
for ( int count = 0; count < threads.length; count++ ) {
Create three Thread
objects and initialize each
with a RunnableObject
// create Thread; initialize object that implements Runnable
threads[ count ] =
new Thread( new RunnableObject(), "Thread " + ( count + 1 ) );
threads[ count ].start(); // begin executing Thread
}
Call thread start
method
 2003 Prentice Hall, Inc.
All rights reserved.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
Outline
}
// determine thread location in threads array
private int getIndex( Thread current )
{
for ( int count = 0; count < threads.length; count++ )
if ( current == threads[ count ] )
return count;
return -1;
}
// called when user switches Web pages; stops all threads
public synchronized void stop()
{
// set references to null to terminate each thread's run method
for ( int count = 0; count < threads.length; count++ )
threads[ count ] = null;
notifyAll(); // notify all waiting threads, so they can terminate
}
// handle button events
public synchronized void actionPerformed( ActionEvent event )
{
RandomCharacter
s.java
Line 66
Line 70
Line 72
Method stop stops
all threads
Set thread references
in array threads to
null
Invoke method
notifyAll to
ready waiting threads
 2003 Prentice Hall, Inc.
All rights reserved.
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
for ( int count = 0; count < checkboxes.length; count++ ) {
if ( event.getSource() == checkboxes[ count ] ) {
suspended[ count ] = !suspended[ count ];
// change label color on suspend/resume
outputs[ count ].setBackground(
suspended[ count ] ? Color.RED : Color.GREEN );
// if thread resumed, make sure it starts executing
if ( !suspended[ count ] )
notifyAll();
Outline
RandomCharacter
s.java
Toggle boolean
value in array
Line 81
suspended
Line 89
Line 98
return;
}
}
} // end method actionPerformed
// private inner class that implements Runnable to control threads
private class RunnableObject implements Runnable {
// place random characters in GUI, variables currentThread and
// index are final so can be used in an anonymous inner class
public void run()
{
Line 102
Call notifyAll to
start ready threads
Class RunnableObject
implements Runnable
interface
Declare method run
 2003 Prentice Hall, Inc.
All rights reserved.
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// get reference to executing thread
final Thread currentThread = Thread.currentThread();
// determine thread's position in array
final int index = getIndex( currentThread );
// loop condition determines when thread should stop; loop
// terminates when reference threads[ index ] becomes null
while ( threads[ index ] == currentThread ) {
// sleep from 0 to 1 second
try {
Thread.sleep( ( int ) ( Math.random() * 1000 ) );
Outline
RandomCharacter
s.java
The while loop executes
Line 112
as long as the index of
array threads equals
Line 120
currentThread
Line 126
// determine whether thread should suspend execution;
// synchronize on RandomCharacters applet object
synchronized( RandomCharacters.this ) {
while ( suspended[ index ] &&
threads[ index ] == currentThread ) {
// temporarily suspend thread execution
RandomCharacters.this.wait();
}
} // end synchronized statement
The
synchronized
block helps suspend
currently executing
thread
Invoke method wait
on applet to place
thread in waiting
state
 2003 Prentice Hall, Inc.
All rights reserved.
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
Outline
} // end try
// if thread interrupted during wait/sleep, print stack trace
catch ( InterruptedException exception ) {
exception.printStackTrace();
}
RandomCharacter
s.java
Line 139
// display character on corresponding JLabel
SwingUtilities.invokeLater(
new Runnable() {
// pick random character and display it
public void run()
{
char displayChar =
alphabet.charAt( ( int ) ( Math.random() * 26 ) );
outputs[ index ].setText(
currentThread.getName()
Anonymous inner
class implements
Runnable interface
+ ": " + displayChar );
}
} // end inner class
); // end call to SwingUtilities.invokeLater
 2003 Prentice Hall, Inc.
All rights reserved.
154
155
} // end while
156
157
System.err.println( currentThread.getName() + " terminating" );
158
159
} // end method run
160
161
} // end private inner class RunnableObject
162
163 } // end class RandomCharacters
Outline
RandomCharacter
s.java
 2003 Prentice Hall, Inc.
All rights reserved.
16.11 (Optional Case Study) Thinking About
Objects: Multithreading
• Concurrent models
– UML contains support for building concurrent models
– Discus how simulation benefits from multithreading
• waitingPassenger must wait for ridingPassenger
to exit Elevator
• Use synchronized method
– Guarantees only one Person in Elevator at a time
 2003 Prentice Hall, Inc. All rights reserved.
16.11 (Optional Case Study) Thinking About
Objects: Multithreading
• Threads, Active Classes and Synchronized method
– UML represents a thread as an active class
• Thick black border in UML diagram indicates an active class
 2003 Prentice Hall, Inc. All rights reserved.
16.11 (Optional Case Study) Thinking About
Objects: Multithreading
• Sequence Diagrams
– Shows interactions among objects
• Shows messages passed among objects over time
– Rectangle enclosing an object name represents that object
• Use same naming conventions as collaboration diagrams
– Lifeline
• Dotted line running down from an object name
• Actions occur on lifeline in chronological order, top to bottom
– Arrows
• Dashed arrows
– Represent “return messages,” return of control to object
• Solid arrows
– A message sent from one object to another
 2003 Prentice Hall, Inc. All rights reserved.
16.11 (Optional Case Study) Thinking About
Objects: Multithreading
• Class diagram now uses active classes
– Elevator and Person are now active classes
 2003 Prentice Hall, Inc. All rights reserved.
Fig. 16.17 Sequence diagram that models a
Person requesting and entering an Elevator
Person
ElevatorShaft
floorButton : Button
elevatorDoor : ElevatorDoor
elevator: Elevator
floorDoor : Door
[ !floorDoor.isDoorOpen() ]
pressButton( )
buttonPressed( )
requestElevator( )
*[ !floorDoor.isDoorOpen() ] wait( )
[Elevator on opposite
Floor of request]
elevator travels
to other floor
elevatorArrived( )
openDoor( )
openDoor( )
setLocation( elevator )
 2003 Prentice Hall, Inc. All rights reserved.
Sequence
continues in
Fig. 16.18
Fig. 16.18 Sequence diagram that models a
Person traveling in an Elevator
Person
elevatorButton : Button
pressButton( )
: Elevator
elevatorDoor : ElevatorDoor
buttonPressed( )
setMoving( true )
Sequence
continued from
Fig. 16.17
closeDoor( )
== 5
seconds
*[ !elevatorDoor.isDoorOpen() ] wait( )
setMoving( false )
changeFloors()
elevatorArrived( )
openDoor( )
setLocation( elevator.getCurrentFloor() )
 2003 Prentice Hall, Inc. All rights reserved.
Fig. 16.19 Revised class diagram of the
elevator simulation
1
Turns
on/off
Light
1
2
Floor
ElevatorSimulation
1
2
1
Signals
arrival
1
1
ElevatorShaft
1
1
Signals
arrival
1
Informs of
pressing
Closes
2
Resets
1
1
Door
Signals
arrival
1
1
1
1
2
Button
Presses
1
1
1
Person
1
1
Waits for
opening
Opens/Closes
1
1
1
ElevatorDoor
1
1
Elevator
Signals
arrival
1
Opens/Closes
Signals
arrival
Rings
1
Bell
 2003 Prentice Hall, Inc. All rights reserved.
1
1
Occupies
Signals
arrival
Travels to
2
1
Location
1
1
Signals
to move
1
Fig. 16.20 Final class diagram with attributes
and operations
Location
- locationName : String
# setLocationName( String ) : void
+ getLocationName( ) : String
+ getButton( ) : Button
+ getDoor( ) : Door
Light
- lightOn : Boolean = false
+ turnOnLight( ) : void
+ turnOffLight( ) : void
ElevatorSimulation
Person
- ID : Integer
- moving : Boolean = true
- location : Location
- maxTravelTime : Integer = 10 * 60
+ doorOpened( ) : void
- numberOfPeople : Integer = 0
+ addPerson( ) : void
Floor
+ getButton( ) : Button
+ getDoor( ) : Door
Bell
Elevator
- moving : Boolean = false
- summoned : Boolean = false
- currentFloor : Location
- destinationFloor : Location
- travelTime : Integer = 5
+ ride( ) : void
+ requestElevator( ) : void
– setMoving( Boolean ) : void
+ getButton( ) : Button
+ getDoor( ) : Door
+ getLocation( ) : Location
 2003 Prentice Hall, Inc. All rights reserved.
+ ringBell( ) : void
Button
- pressed : Boolean = false
+ resetButton( ) : void
+ pressButton( ) : void
Door
- open : Boolean = false
+ openDoor( ) : void
+ closeDoor( ) : void
16.12 (Optional) Discovering Design
Patterns: Concurrent Design Patterns
• Concurrency Design Patterns
– Single-Threaded Execution design pattern
• Stops several threads from invoking a method concurrently
– Guarded Suspension design pattern
• Suspends and resumes a threads activity when a condition met
– Balking design pattern
• Causes method to balk if an object occupies a certain state
– Read/Write Lock design pattern
• Multiple read on an object but exclusive write
– Two-Phase Termination design pattern
• Uses two-phase termination process to ensure resources freed
 2003 Prentice Hall, Inc. All rights reserved.