
- •Contents
- •Preface
- •Introduction to Computers, the Internet and the Web
- •1.3 Computer Organization
- •Languages
- •1.9 Java Class Libraries
- •1.12 The Internet and the World Wide Web
- •1.14 General Notes about Java and This Book
- •Sections
- •Introduction to Java Applications
- •2.4 Displaying Text in a Dialog Box
- •2.5 Another Java Application: Adding Integers
- •2.8 Decision Making: Equality and Relational Operators
- •Introduction to Java Applets
- •3.2 Sample Applets from the Java 2 Software Development Kit
- •3.3 A Simple Java Applet: Drawing a String
- •3.4 Two More Simple Applets: Drawing Strings and Lines
- •3.6 Viewing Applets in a Web Browser
- •3.7 Java Applet Internet and World Wide Web Resources
- •Repetition)
- •Class Attributes
- •5.8 Labeled break and continue Statements
- •5.9 Logical Operators
- •Methods
- •6.2 Program Modules in Java
- •6.7 Java API Packages
- •6.13 Example Using Recursion: The Fibonacci Series
- •6.16 Methods of Class JApplet
- •Class Operations
- •Arrays
- •7.6 Passing Arrays to Methods
- •7.8 Searching Arrays: Linear Search and Binary Search
- •Collaboration Among Objects
- •8.2 Implementing a Time Abstract Data Type with a Class
- •8.3 Class Scope
- •8.4 Controlling Access to Members
- •8.5 Creating Packages
- •8.7 Using Overloaded Constructors
- •8.9 Software Reusability
- •8.10 Final Instance Variables
- •Classes
- •8.16 Data Abstraction and Encapsulation
- •9.2 Superclasses and Subclasses
- •9.5 Constructors and Finalizers in Subclasses
- •Conversion
- •9.11 Type Fields and switch Statements
- •9.14 Abstract Superclasses and Concrete Classes
- •9.17 New Classes and Dynamic Binding
- •9.18 Case Study: Inheriting Interface and Implementation
- •9.19 Case Study: Creating and Using Interfaces
- •9.21 Notes on Inner Class Definitions
- •Strings and Characters
- •10.2 Fundamentals of Characters and Strings
- •10.21 Card Shuffling and Dealing Simulation
- •Handling
- •Graphics and Java2D
- •11.2 Graphics Contexts and Graphics Objects
- •11.5 Drawing Lines, Rectangles and Ovals
- •11.9 Java2D Shapes
- •12.12 Adapter Classes
- •Cases
- •13.3 Creating a Customized Subclass of JPanel
- •Applications
- •Controller
- •Exception Handling
- •14.6 Throwing an Exception
- •14.7 Catching an Exception
- •Multithreading
- •15.3 Thread States: Life Cycle of a Thread
- •15.4 Thread Priorities and Thread Scheduling
- •15.5 Thread Synchronization
- •15.9 Daemon Threads
- •Multithreading
- •Design Patterns
- •Files and Streams
- •16.2 Data Hierarchy
- •16.3 Files and Streams
- •Networking
- •17.2 Manipulating URIs
- •17.3 Reading a File on a Web Server
- •17.4 Establishing a Simple Server Using Stream Sockets
- •17.5 Establishing a Simple Client Using Stream Sockets
- •17.9 Security and the Network
- •18.2 Loading, Displaying and Scaling Images
- •18.3 Animating a Series of Images
- •18.5 Image Maps
- •18.6 Loading and Playing Audio Clips
- •18.7 Internet and World Wide Web Resources
- •Data Structures
- •19.4 Linked Lists
- •20.8 Bit Manipulation and the Bitwise Operators
- •Collections
- •21.8 Maps
- •21.9 Synchronization Wrappers
- •21.10 Unmodifiable Wrappers
- •22.2 Playing Media
- •22.3 Formatting and Saving Captured Media
- •22.5 Java Sound
- •22.8 Internet and World Wide Web Resources
- •Hexadecimal Numbers

Chapter 15 |
Multithreading |
841 |
caller immediately. The caller then executes concurrently with the launched thread. The start method throws an IllegalThreadStateException if the thread it is trying to start has already been started.
The static method sleep is called with an argument specifying how long the currently executing thread should sleep (in milliseconds); while a thread sleeps, it does not contend for the processor, so other threads can execute. This can give lower priority threads a chance to run.
The interrupt method is called to interrupt a thread. The static method interrupted returns true if the current thread has been interrupted and false otherwise. A program can invoke a specific thread’s isInterrupted method to determine whether that thread has been interrupted.
Method isAlive returns true if start has been called for a given thread and the thread is not dead (i.e., its controlling run method has not completed execution).
Method setName sets a Thread’s name. Method getName returns the name of the Thread. Method toString returns a String consisting of the name of the thread, the priority of the thread and the thread’s ThreadGroup (discussed in Section 15.11).
The static method currentThread returns a reference to the currently executing Thread.
Method join waits for the Thread to which the message is sent to die before the calling Thread can proceed; no argument or an argument of 0 milliseconds to method join indicates that the current Thread will wait forever for the target Thread to die before the calling Thread proceeds. Such waiting can be dangerous; it can lead to two particularly serious problems called deadlock and indefinite postponement. We will discuss these momentarily.
Testing and Debugging Tip 15.2
Method dumpStack is useful for debugging multithreaded applications. A program calls static method dumpStack to print a method-call stack trace for the current Thread.
15.3 Thread States: Life Cycle of a Thread
At any time, a thread is said to be in one of several thread states (illustrated in Fig. 15.1). Let us say that a thread that was just created is in the born state. The thread remains in this state until the program calls the thread’s start method, which causes the thread to enter the ready state (also known as the runnable state). The highest priority ready thread enters the running state (i.e., the thread begins executing), when the system assigns a processor to the thread. A thread enters the dead state when its run method completes or terminates for any reason—a dead thread eventually will be disposed of by the system.
One common way for a running thread to enter the blocked state is when the thread issues an input/output request. In this case, a blocked thread becomes ready when the I/O for which it is waiting completes. A blocked thread cannot use a processor even if one is available.
When the program calls method sleep in a running thread, that thread enters the sleeping state. A sleeping thread becomes ready after the designated sleep time expires. A sleeping thread cannot use a processor even if one is available. If the program calls method interrupt on a sleeping thread, that thread exits the sleeping state and becomes ready to execute.

842 |
Multithreading |
Chapter 15 |
born
start
|
|
|
|
|
y |
|
|
|
|
|
A |
l |
l |
|
|
|
|
f |
|
|
|
|
y |
|
|||
|
|
|
i |
|
|
|
f |
|
|
||||
|
|
t |
|
|
|
i |
|
|
|
||||
|
o |
|
|
|
t |
|
|
|
|
||||
n |
|
|
|
o |
|
|
|
|
|
||||
|
|
|
n |
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
r |
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
o |
|
|
|
|
|
|
|
|
|
quantum expiration
yield interrupt
|
|
t |
|
|
|
|
|
|
i |
|
|
|
|
p |
|
a |
|
|
|
|
|
||
w |
|
|
|
|
e |
e |
|
|
|
|
|
l |
|
||
|
|
|
s |
|
|
||
|
|
|
|
|
|
||
|
|
|
|
|
|
|
ready
dispatch (assign a
processor)
running
|
i |
|
|
|
|
s |
|
|
|
|
|
s |
|
|
c |
|
|
u |
e |
|
|
|
|
I |
|
|
|
|
/ |
o |
|
|
|
O |
m |
|
|
|
|
p |
|
|
|
|
|
l |
|
|
|
|
e |
|
|
|
|
t |
|
|
|
|
e |
|
|
I /
O
c
o
m
p l e
t i
o
n
request
waiting |
sleeping |
dead |
blocked |
sleep interval expires
Fig. 15.1 State diagram showing the Life cycle of a thread.
When a running thread calls wait, the thread enters a waiting state for the particular object on which wait was called. One thread in the waiting state for a particular object becomes ready on a call to notify issued by another thread associated with that object. Every thread in the waiting state for a given object becomes ready on a call to notifyAll by another thread associated with that object. The wait, notify and notifyAll methods will be discussed in more depth shortly, when we consider monitors.
A thread enters the dead state when its run method either completes or throws an uncaught exception.
15.4 Thread Priorities and Thread Scheduling
Every Java applet or application is multithreaded. Every Java thread has a priority in the range Thread.MIN_PRIORITY (a constant of 1) and Thread.MAX_PRIORITY (a constant of 10). By default, each thread is given priority Thread.NORM_PRIORITY (a constant of 5). Each new thread inherits the priority of the thread that creates it.
Some Java platforms support a concept called timeslicing and some do not. Without timeslicing, each thread in a set of equal-priority threads runs to completion (unless the thread leaves the running state and enters the waiting, sleeping or blocked state, or the

Chapter 15 |
Multithreading |
843 |
thread gets interrupted by a higher priority thread) before that thread’s peers get a chance to execute. With timeslicing, each thread receives a brief burst of processor time called a quantum during which that thread can execute. At the completion of the quantum, even if that thread has not finished executing, the operating system takes the processor away from that thread and gives it to the next thread of equal priority (if one is available).
The job of the Java scheduler is to keep the highest priority thread running at all times, and if timeslicing is available, to ensure that several equally high-priority threads each execute for a quantum in round-robin fashion (i.e., these threads can be timesliced). Figure 15.2 illustrates Java’s multilevel priority queue for threads. In the figure, threads A and B each execute for a quantum in round-robin fashion until both threads complete execution. Next, thread C runs to completion. Then, threads D, E and F each execute for a quantum in round-robin fashion until they all complete execution. This process continues until all threads run to completion. Note that new higher-priority threads could postpone— possibly indefinitely—the execution of lower priority threads. Such indefinite postponement often is referred to more colorfully as starvation.
A thread’s priority can be adjusted with method setPriority, which takes an int argument. If the argument is not in the range 1 through 10, setPriority throws an IllegalArgumentException. Method getPriority returns the thread’s priority.
A thread can call the yield method to give other threads a chance to execute. Actually, whenever a higher priority thread becomes ready, the operating system preempts the current thread. So, a thread cannot yield to a higher priority thread, because the first thread would have been preempted when the higher priority thread became ready. Similarly, yield always allows the highest priority-ready thread to run, so if only lower priority threads are ready at the time of a yield call, the current thread will be the highest priority thread and will continue executing. Therefore, a thread yields to give threads of an equal priority a chance to run. On a timesliced system this is unnecessary, because threads of equal priority will each execute for their quantum (or until they lose the processor for some other reason), and other threads of equal priority will execute in roundrobin fashion. Thus yield is appropriate for nontimesliced systems in which a thread would ordinarily run to completion before another thread of equal priority would have an opportunity to run.
Performance Tip 15.3
On nontimesliced systems, cooperating threads of equal priority should periodically call
yield to enable their peers to proceed smoothly.
Portability Tip 15.2
Java applets and applications should be programmed to work on all Java platforms to realize
Java’s goal of true portability. When designing applets and applications that use threads, you must consider the threading capabilities of all the platforms on which the applets and applications will execute.
A thread executes unless it dies, it becomes blocked by the operating system for input/ output (or some other reason), it calls sleep, it calls wait, it calls yield, it is preempted by a thread of higher priority or its quantum expires. A thread with a higher priority than the running thread can become ready (and hence preempt the running thread) if a sleeping thread finishes sleeping, if I/O completes for a thread waiting for that I/O or if either notify or notifyAll is called on a thread that has called wait.

844 |
Multithreading |
Chapter 15 |
|
|
|
Ready threads |
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 10 |
|
|
|
A |
|
|
B |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 9 |
|
|
|
C |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 7 |
|
|
|
D |
|
|
E |
|
|
|
F |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 6 |
|
|
|
G |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 5 |
|
|
|
H |
|
|
I |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 2 |
|
|
|
J |
|
|
K |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Priority 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Fig. 15.2 Java thread priority scheduling.
The application of Fig. 15.3 demonstrates basic threading techniques, including creation of a class derived from Thread, construction of a Thread and using the Thread class sleep method. Each thread of execution we create in the program displays its name after sleeping for a random amount of time between 0 and 5 seconds. You will see that the main method (i.e., the main thread of execution) terminates before the application terminates. The program consists of two classes—ThreadTester (lines 4–28) and PrintThread (lines 33–71).
Class PrintThread inherits from Thread, so that each object of the class can execute in parallel. The class consists of instance variable sleepTime, a constructor and a

Chapter 15 |
Multithreading |
845 |
run method. Variable sleepTime stores a random integer value chosen when the program creates a PrintThread object. Each PrintThread object sleeps for the amount of time specified by its sleepTime, then outputs its name.
The PrintThread constructor (lines 38–48) initializes sleepTime to a random integer between 0 and 4999 (0 to 4.999 seconds). Then, the constructor outputs the name of the thread and the value of sleepTime to show the values for the particular PrintThread being constructed. The name of each thread is specified as a String argument to the PrintThread constructor and is passed to the superclass constructor at line 40. [Note: It is possible to allow class Thread to choose a name for your thread by using the Thread class’s default constructor.
1// Fig. 15.3: ThreadTester.java
2 // Show multiple threads printing at different intervals.
3
4 public class ThreadTester {
5
6// create and start threads
7public static void main( String args[] )
8{
9 PrintThread thread1, thread2, thread3, thread4;
10
11// create four PrintThread objects
12thread1 = new PrintThread( "thread1" );
13thread2 = new PrintThread( "thread2" );
14thread3 = new PrintThread( "thread3" );
15thread4 = new PrintThread( "thread4" );
17 System.err.println( "\nStarting threads" );
18
19// start executing PrintThreads
20thread1.start();
21thread2.start();
22thread3.start();
23thread4.start();
24
25System.err.println( "Threads started\n" );
26}
27
28 } // end class ThreadTester
29
30// Each object of this class picks a random sleep interval.
31// When a PrintThread executes, it prints its name, sleeps,
32// prints its name again and terminates.
33class PrintThread extends Thread {
34private int sleepTime;
35
36// PrintThread constructor assigns name to thread
37// by calling superclass Thread constructor
Fig. 15.3 Multiple threads printing at random intervals (part 1 of 3).

846 |
Multithreading |
Chapter 15 |
38public PrintThread( String name )
39{
40super( name );
41
42// sleep between 0 and 5 seconds
43sleepTime = (int) ( Math.random() * 5000 );
45// display name and sleepTime
46System.err.println(
47"Name: " + getName() + "; sleep: " + sleepTime );
48}
49
50// control thread's execution
51public void run()
52{
53// put thread to sleep for a random interval
54try {
55 |
System.err.println( getName() + " going to sleep" ); |
56 |
|
57 |
// put thread to sleep |
58Thread.sleep( sleepTime );
59}
60
61// if thread interrupted during sleep, catch exception
62// and display error message
63catch ( InterruptedException interruptedException ) {
64System.err.println( interruptedException.toString() );
65}
66
67// print thread name
68System.err.println( getName() + " done sleeping" );
69}
70
71 } // end class PrintThread
Name: thread1; sleep: 3593
Name: thread2; sleep: 2653
Name: thread3; sleep: 4465
Name: thread4; sleep: 1318
Starting threads
Threads started
thread1 going to sleep thread2 going to sleep thread3 going to sleep thread4 going to sleep thread4 done sleeping thread2 done sleeping thread1 done sleeping thread3 done sleeping
Fig. 15.3 Multiple threads printing at random intervals (part 2 of 3).

Chapter 15 |
Multithreading |
847 |
Name: thread1; sleep: 2753
Name: thread2; sleep: 3199
Name: thread3; sleep: 2797
Name: thread4; sleep: 4639
Starting threads
Threads started
thread1 going to sleep thread2 going to sleep thread3 going to sleep thread4 going to sleep thread1 done sleeping thread3 done sleeping thread2 done sleeping thread4 done sleeping
Fig. 15.3 Multiple threads printing at random intervals (part 3 of 3).
When the program invokes a PrintThread’s start method (inherited from Thread), the PrintThread object enters the ready state. When the system assigns a processor to the PrintThread object, it enters the running state and its run method begins execution. Method run (lines 51–69) prints a String in the command window indicating that the thread is going to sleep (line 55), then invokes the sleep method (line 58) to place the thread into a sleeping state. At this point, the thread loses the processor, and the system allows another thread to execute. When the thread awakens, it is placed in a ready state again until the system assigns to the thread. When the PrintThread object enters the running state again, line 68 outputs the thread’s name (indicating that the thread is done sleeping), the run method terminates and the thread object enters the dead state. Note that method sleep can throw a checked InterruptedException (if another thread invokes the sleeping thread’s interrupt method); therefore, sleep must be called in a try block (in this example, we simply output the String representation of the exception if one occurs). Note that this example uses System.err rather than System.out to output lines of text. System.err represents the standard error object, which outputs error messages (normally to the command window). System.out performs buffered output—it is possible that a message output with System.out will not be output immediately. On the other hand, System.err uses unbuffered output—messages appear immediately when they are output. Using System.err in a multithreaded program helps ensure that the messages from our program are output in the correct order.
Class ThreadTester’s main method (lines 7–26) creates four objects of class PrintThread (lines 12–15) and invokes the Thread class start method on each one (lines 20–23) to place all four PrintThread objects in a ready state. Note that the program terminates execution when the last PrintThread awakens and prints its name. Also, note that the main method (i.e., the main thread of execution) terminates after starting the four PrintThreads, but the application does not terminate until the last thread dies.