4003-440-02 Operating Systems I
Module 3. Thread Programming -- Lecture Notes
Prof. Alan Kaminsky -- Winter Quarter 2012
Rochester Institute of Technology -- Department of Computer Science
Introduction
- Reasons for writing a multi-threaded program
- To utilize multiple hardware processors (parallel programming)
- To keep executing other threads when one thread has to block
- To implement a simpler algorithm
- Principal Java platform classes related to thread programming
- Package java.lang
- Class Thread
- Interface Runnable
- Package java.util.concurrent (JDK 1.5)
- Interface Callable<V>
- Interface Future<V>
- Interface ExecutorService
- Class Executors
- Additional Java platform classes related to thread programming
- Package java.lang
- Class ThreadGroup
- Class ThreadLocal<T>
- Class InheritableThreadLocal<T>
A Sequential Program
-
Class UC1 is the main program for the URL Counter Version 1. It counts lines,
words, and bytes in the URLs given on the command line. It is a sequential
(single-threaded) program.
Usage: java edu.rit.os1.UC1 url . . .
- Package edu.rit.os1
- Running time measurements
Thread Creation, Alternative 1
- Problem: Program UC1 spends a lot of time doing nothing, waiting for URL data to download
- Solution: Do each URL in its own separate thread
-
Class UC2 is the main program for the URL Counter Version 2. It counts lines,
words, and bytes in the URLs given on the command line. It is a
multi-threaded program where each URL counter object is a subclass of class
Thread.
Usage: java edu.rit.os1.UC2 url . . .
- Package edu.rit.os1
- Pattern
- Write a subclass of class Thread, override the run() method
- Create an instance of the Thread subclass
- Call the thread's start() method
- Original thread returns from start() and continues executing
- New thread executes the thread's run() method
- When the run() method returns, the new thread terminates
- "synchronized (System.out) { ... }" in class URLCounterThread
- Running time measurements
Waiting For Thread Termination
- Problem: Program UC2 prints its running time before any of the threads execute!
- Solution: The main program must wait for all the threads to terminate before printing the running time
-
Class UC3 is the main program for the URL Counter Version 3. It counts lines,
words, and bytes in the URLs given on the command line. It is a
multi-threaded program where each URL counter object is a subclass of class
Thread. Before returning, the main
program waits for all the threads to terminate.
Usage: java edu.rit.os1.UC3 url . . .
- Package edu.rit.os1
- Pattern
- To wait for a target thread to terminate, call join() on the target thread
- join() does not return until the target thread terminates
- The thread calling join() is blocked until the target thread terminates
- Running time measurements
Thread Creation, Alternative 2
-
Class UC4 is the main program for the URL Counter Version 4. It counts lines,
words, and bytes in the URLs given on the command line. It is a
multi-threaded program where each URL counter object implements interface
Runnable but is not a subclass of
class Thread. Before returning, the
main program waits for all the threads to terminate.
Usage: java edu.rit.os1.UC4 url . . .
- Package edu.rit.os1
- Pattern
- Write a class that implements interface Runnable, implement the run() method
- Create an instance of the runnable object
- Create an instance of class Thread, passing the runnable object to the thread constructor
- Call the thread's start() method
- Original thread returns from start() and continues executing
- New thread executes the runnable object's run() method
- When the run() method returns, the new thread terminates
- Running time measurements
Thread Creation, Alternative 3
- Problem: That's a fair rigamarole to create all the threads and wait for them all to terminate -- isn't there a simpler way?
- Solution: Use a thread pool -- new in JDK 1.5
-
Class UC5 is the main program for the URL Counter Version 5. It counts lines,
words, and bytes in the URLs given on the command line. It is a
multi-threaded program where each URL counter object implements interface
Runnable but is not a subclass of
class Thread. The main program uses a
thread pool rather than creating threads directly.
Usage: java edu.rit.os1.UC5 url . . .
- Package edu.rit.os1
- Pattern
- Write a class that implements interface Runnable, implement the run() method
- Create an ExecutorService (thread pool) using a static method of class Executors
- Several different kinds of thread pools are available
- We will generally use a cached thread pool, which reuses idle threads if possible and creates new threads if necessary
- Create an instance of the runnable object and pass it to the thread pool's execute() method
- Original thread returns from execute() and continues executing
- Thread pool executes the runnable object's run() method in a separate thread
- To wait for all threads to terminate, call shutdown() followed by awaitTermination() on the thread pool
- Running time measurements
Getting Results From Thread Executions
- Problem: Suppose we want to add up the counts for all the URLs
- Solution: Use futures to return results back to the main thread -- new in JDK 1.5
-
Class UC6 is the main program for the URL Counter Version 5. It counts lines,
words, and bytes in the URLs given on the command line. It is a
multi-threaded program where each URL counter object implements interface
Runnable but is not a subclass of
class Thread. The main program uses a
thread pool rather than creating threads directly. The main program also
prints the total lines, words, and bytes in all the URLs.
Usage: java edu.rit.os1.UC6 url . . .
- Package edu.rit.os1
- Pattern
- Write a class that implements interface Callable<V>, implement the call() method to return a value of type V
- Create an ExecutorService (thread pool) using a static method of class Executors
- Create an instance of the callable object and pass it to the thread pool's submit() method
- submit() returns a future, an instance of interface Future<V>, to the original thread
- Save the future somewhere
- Thread pool executes the callable object's call() method in a separate thread and stores the call() method's return value in the corresponding future
- To get the callable object's return value, original thread calls get() on the future -- this blocks until the return value becomes available
- Must still call shutdown() on the thread pool
- Running time measurements
Segue
- Problem: But now we're back to processing the threads' results sequentially. Can't we accumulate the total counts concurrently also?
- Problem: That's a fair rigamarole to store all the futures and then go back and process them all again -- isn't there a simpler way?
- Solution: See Module 4, Thread Coordination.
|
Operating Systems I
|
|
•
|
|
4003-440-02
|
|
•
|
|
Winter Quarter 2012
|
|
Course Page
|
|
Alan Kaminsky
|
|
•
|
|
Department of Computer Science
|
|
•
|
|
Rochester Institute of Technology
|
|
•
|
|
4486 +
2220 =
6706
|
|
Home Page
|
Copyright © 2008 Alan Kaminsky.
All rights reserved.
Last updated 27-Aug-2008.
Please send comments to ark@cs.rit.edu.
|