Download JDC_Lecture18 - Computer Science

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Thread (computing) wikipedia , lookup

Transcript
UMass Lowell Computer Science 91.460
Java and Distributed Computing
Prof. Karen Daniels
Fall, 2000
Lecture 18
Advanced Java Concepts
Threads and Multithreading
[Java 2: The Complete Reference: Chapter 11]
[Deitel: Chapter 15]
Fri. 10/27 – Mon. 10/30
Homework Status
HW# Assigned Due
Graded
Submitted
Pending
1
2
3
4
5
6
7
Fri, 9/8
Fri, 9/15
Fri, 9/22
Fri, 10/6
Fri, 10/13
Fri, 10/20
Fri, 10/27
9/15, 9/18
Fri, 9/22
Fri, 9/29
Fri, 10/13
Fri, 10/20
Fri, 10/27
Fri, 11/3
Thread Demo
“Nervous Text”
Some Definitions




Multiprocessing - The simultaneous processing of
two or more portions of the same program on two
or more processing units
Multiprogramming - The simultaneous processing
of multiple programs (OS processes) on one or
more processing units
Multitasking operating system - an OS that
supports multiprogramming
Multithreading ???
Multithreading

The “simultaneous” * processing of two or more
portions (threads) of the same program (OS
process)


Might take advantage of multiple CPUs when present
A thread can be thought of as a light-weight
process that you control (rather than the OS)


Requires less overhead than full-fledged processes
Makes sharing resources (e.g., memory) easier
* Logical but not necessarily truly physical concurrency
Multithreading vs. Multiprogramming
Multiprogramming
CPU 1
Program 1
...
Program n
...
CPU m
Multithreading
Program 1
CPU 1
Thread 1A Thread 1B
...
...
Program n
Thread nA
Thread nB
Thread nC
Source: Java 2 Certification
CPU m
Why Use Threads?





Can provide real or apparent speed up (e.g., start
editing a large file before it is completely loaded
in memory)
Can support arbitrary service requests easily
Can support shared use of a common resource
Is (relatively) easy to do in Java in a (mostly)
portable way
General rule of thumb - if a piece of code takes a
long time to run and is somewhat independent of
the rest of the program, put it in a thread
Thread States





Born - created, needs to be started
Ready (runnable) - eligible to be run
Running - actually executing
Waiting - asleep, blocked (for I/O), etc.
Dead - processing completed, “that’s all she wrote”
Waiting
Born
Ready
Running
Dead
This is a very simple example of a state diagram. State
transition diagrams with transition conditions labeling the
arrows are helpful aids to designing good multithreaded code.
Life Cycle of a Java Thread
(more detail)
Source: Deitel & Deitel
Thread Scheduling
The JVM has to select which thread(s) to
run (move from ready to running states) at
what time
 Two kinds of scheduling:

 Preemptive
(UNIX)
 Time slicing (Win32, Macintosh)
Preemptive Scheduling

The highest priority thread runs until



It dies
It “puts itself to sleep”
It is preempted by a higher priority thread



A higher-priority thread comes into existence
A previous thread’s priority changes
Preemptive scheduling is predictable, but can
result in low-priority threads never running
Time Slicing
Threads execute for a specific slice of time
 Scheduler then decides whether to keep
thread running or “give the CPU to” another
thread
 Less predictable than preemptive
scheduling, but can handle “selfish” threads

Synchronization




The use of threads presents a need for
coordinating their activities
Synchronization is temporal coordination of
simultaneous activities
Synchronization allows communication about
things/events of mutual interest across threads
Synchronization is needed to support mutual
exclusion
Mutual Exclusion

Multiple threads present a potential pitfall simultaneous access to shared resources
 Thread A want
to read the value of a variable,
think about it for while, and then change it
 After Thread A reads the value, but before it
writes the new value, Thread B changes its
value
 Thread B’s change gets lost
Semaphores




Semaphores are primitives that support mutual
exclusion
Allow multiple programs to read/write shared
information
Identify critical regions of code that need
exclusive access to a shared resource
Usage:




Process A wants shared resource, tells that resource’s
semaphore to wait
System suspends Process A until resource is available
System then wakes up Process A and gives it exclusive
use of the resource
When Process A is finished with the resource, tells the
semaphore to proceed (releases the resource)
Semaphores (continued)

Semaphore mechanism uses:





A sequencer S: integer variable
Atomic Wait operation P:
 P(S): Wait until S>0 and then S-Atomic Signal operation V:
 V(S): S++
Allows a process to block itself to wait for an event and
then be awakened by another process when the event
occurs
To control access to a single resource, use binary
semaphore
Source: Structured Concurrent Programming with
Operating Systems Applications
The Monitor Concept
• Object-oriented: local data +
“methods”
• Scheduler controls order of
resource allocation
• Condition variables determine
can cause process to block
• Guard allows only 1 process
to execute in monitor at a time
• Monitor supports mutual
exclusion for each procedure
Source: Operating Systems:
Advanced Concepts
Java’s Approach to Threads

Java was designed with threads in mind
 class
Thread
 class Object
 synchronized statements and methods

uses Monitor concept from Operating Systems
 class
ThreadGroup
java.lang.Thread


Implements the java.lang.Runnable interface
Basic methods:





run() - the thread’s execution entry point (invoked by
the JVM thread scheduler)
start() - put the (new) thread in the ready state, then
returns immediately to the launching thread
isAlive() - the thread has been started and is not dead
getName() - returns the thread’s name (has a JVMassigned default or can be specified )
toString() - like getName(), but includes the priority
and ThreadGroup name
java.lang.Thread (concluded)

Basic methods (concluded):





setPriority() - sets the thread’s (integer, 1 to 10)
priority
currentThread() - returns the current Thread (static)
sleep() - puts the (currentThread) thread to sleep for a
specified time so that other (e.g., lower-priority)
threads can execute (static)
interrupt() - wakes up a thread
join() - the thread that invokes this on another thread
waits for the other thread to die before proceeding
Thread Specification (1 of 3)
public class Thread implements Runnable {
public final static int MIN_PRIORITY = 1;
public final static int MAX_PRIORITY = 10;
public final static int NORM_PRIORITY = 5;
public Thread();
public Thread(String name);
public Thread(Runnable runObject);
public Thread(Runnable runObject, String name);
public Thread(ThreadGroup group, String name)
throws SecurityException, IllegalThreadStateException;
public Thread(ThreadGroup group, Runnable runObject)
throws SecurityException, IllegalThreadStateException;
public Thread(ThreadGroup group, Runnable runObject, String name)
throws SecurityException, IllegalThreadStateException;
Thread Specification (2 of 3)
public String toString();
public void checkAccess() throws SecurityException;
public void run();
public void start()
throws IllegalThreadStateException;
public final String getName();
public final void setName(String name)
throws SecurityException;
public final ThreadGroup getThreadGroup();
public final int getPriority();
public final void setPriority(int newPriority)
throws SecurityException, IllegalArgumentException;
public final boolean isDaemon();
public final void setDaemon(boolean on)
throws SecurityException, IllegalThreadStateException;
public final boolean isAlive();
public int countStackFrames();
Thread Specification (3 of 3)
public final void join()
throws InterruptedException;
public final void join(long millis)
throws InterruptedException;
public final void join(long millis, int nanos)
throws InterruptedException;
public void interrupt();
public boolean isInterrupted();
public static boolean interrupted();
public static Thread currentThread();
public static void dumpStack();
public static void yield();
public static void sleep(long millis)
throws InterruptedException;
public static void sleep(long millis, int nanos)
throws InterruptedException;
public void destroy(); }
Creating Threads

Option #1





Define a subclass of class Thread
Override the run() method
Create an instance of the subclass
Invoke the instance’s start() method
Option #2





Define a class that implements the Runnable interface
Implement the run() method
Create an instance of the class
Pass the instance to the Thread class’ constructor
Invoke the thread’s start() method
Example of Creating a Thread:
Option #1
public class MyThread1 extends Thread {
public void run() { // do something useful }
public static void main(String args[]) {
MyThread1 myThread = new MyThread1( );
myThread.start();
}
}
Option #1
Define a subclass of class Thread
Override the run() method
Create an instance of the subclass
Invoke the instance’s start() method
Example of Creating a Thread:
Option #2
public class MyThread2 implements Runnable {
public void run( ) { // do something useful }
public static void main(String args[]) {
Thread myThread = new Thread(new MyThread2( ));
myThread.start( );
}
}
Option #2
Define a class that implements the Runnable interface
Implement the run() method
Create an instance of the class
Pass the instance to the Thread class’ constructor
Invoke the thread’s start() method
Daemon Threads



A utility thread for other threads (e.g., the garbage
collector)
Run in the background
Their (live) existence does not prevent a program
from terminating


When the last non-daemon thread dies, the program
exits
Daemon status must be set before the thread starts
Running a Thread

JVM starts up, invokes some class’ main method


Eventually, a new thread gets created and its
start() method is invoked



Makes the thread ready
When selected by the JVM scheduler, the new
thread’s run method is invoked


That class is started in a single, non-daemon thread
Continues running until run() returns, or aborts
Dead threads are eventually cleaned up
JVM continues until all non-daemon threads have
stopped (died)
Making a Thread Wait

The currentThread can be put into a waiting state:


By invoking Thread.sleep()
By performing an input/output request



The thread becomes ready when the I/O is finished
By invoking an Object’s wait() method
By the scheduler when a higher priority thread is
selected to execute

E.g., the higher priority thread’s sleep period ends, its I/O
finishes, or it has been notified out of a wait invocation
Interrupts
A waiting Thread can be interrupted by
explicitly invoking its interrupt() method
 The interrupted thread moves from waiting
to ready state
 When selected for running, the interrupted
thread “jumps to” its InterruptedException
handler

Example of Handling an Interrup
public class MyThread extends Thread {
...
void foo() {
try {
// do something
sleep(10000);
} catch (InterruptException x) {
System.out.println(“Interrupted”);
}
}
}
Thread Synchronization

An object with a synchronized method is a
monitor


An object has a single lock


The thread executing a synchronized method has that
object’s lock
Only one synchronized method in a class can be
active on an object at a time


e.g., public synchronized void foo() { // do stuff }
All other threads that want to invoke any synchronized
method on that object must wait (there is only one lock
for the entire object)
When the synchronized method returns, the lock
on that object is released
Thread Synchronization
(concluded)




While executing a synchronized method, a thread
might decide that it can’t proceed further and
voluntarily give up control by invoking the
object’s wait() method
When finished executing a synchronized method,
a thread can decide to invoke the object’s notify or
notifyAll method() to let other threads know that
its done
A thread that is waiting to get a lock on an object
must either be notified or interrupted (or it will
wait forever)
Only call wait(), notify(), or notifyAll() if you
have a lock on the object (e.g., are in a
synchronized method)
synchronized Static Methods
You can get a lock on a class (actually, the
class’s Class object) by creating a
synchronized static method
 Only one thread can execute a (any)
synchronized static method at a time

Synchronized Blocks


Arbitrary code blocks (marked by braces { }) can
be synchronized
Syntax:




1) synchronized (objectReference) { statements }
2) synchronized (className) { statements }
The currentThread must have a lock on the object
(or class) before it can execute the statements
Can be used with any object/class, not just the one
for the object/class of the method you’re in
class Object and Threads

Class Object has three thread-related methods:




wait() - puts the running thread that invokes this
method into a waiting state
notify() - moves some other thread that is waiting on
that object into the ready state
notifyAll() - moves all other threads that are waiting on
that object into the ready state
Every object has a wait set which is a list of
Threads that are waiting to get a lock on the object
wait()




May specify time period (or indefinite wait if 0 or
none specified)
Must have a lock on the object
Causes lock to be relinquished
Puts the invoking thread into wait state until:




Some other thread invokes notify (and this thread
happens to get picked) or notifyAll
Some other thread interrupts it
The specified time period has elapsed
It then goes into the ready (runnable) state
notify()
Must have a lock on the object
 The invoking thread states its willingness to
relinquish its lock on the object
 Moves an arbitrary thread (at the discretion
of the implementation) that is waiting on
that lock from the waiting to the ready state

 The
selected thread has no special priority in
getting the lock
notifyAll()
Must have a lock on the object
 The invoking thread states its willingness to
relinquish its lock on the object
 Moves all threads that are waiting on that
lock from the waiting to the ready state

 The
threads have no special priority in getting
the lock
java.lang.ThreadGroup

Every Thread belongs to exactly one ThreadGroup






There’s a default “system” ThreadGroup
Can interrupt all Threads in a ThreadGroup
Can notifyAll Threads in a ThreadGroup
Can get/set the maxPriority of the Threads in a
ThreadGroup
Can be a daemon ThreadGroup (Threads created by
referencing a daemon ThreadGrop in their constructor
become daemon Threads)
ThreadGroups can be hierarchical (can have one
parent)

An invocation on the parent ThreadGroup is also called
on all of its children
An Aside - the Class class

Objects of this class, called class
descriptors, are automatically created by the
JVM when a class (or interface) is loaded
 Accessed
by an Object’s getClass method
 Can get the class’s name, superclass, interfaces
 Can create instances of the class (in lieu of
using the class’ constructors)
 Can be locked for thread synchronization
purposes