Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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