Download presentation
Presentation is loading. Please wait.
Published byAron Porter Modified over 6 years ago
1
Threads Java Threads "The real payoff of concurrent execution arises not from the fact that applications can be speeded up by artificially introducing concurrency, but from the fact that the real world functions by the execution of concurrent activities.” – P. Wegner ©SoftMoore Consulting
2
Importance of Concurrent Programming Facilities
Threads Importance of Concurrent Programming Facilities Concurrent execution (on multiprocessing hardware) can improve program performance. Many applications are modeled more naturally as systems of concurrently executing threads. A concurrent program preserves the structure of a concurrent problem. Concurrent programming facilities enhance the programmer’s ability to “invent” concurrent solutions. ©SoftMoore Consulting
3
Threads Threads A thread (a.k.a., a lightweight process) is a single sequential flow of control within a Java program. A thread may operate in parallel with other threads. Concurrency may be real (if the underlying computer has more than one processor) or simulated (via interleaved execution on a single processor). Conceptually it is best to think of each thread as having its own personal processor. Java provides support for concurrency at the class level, not at the statement level. ©SoftMoore Consulting
4
Concurrency Utilities in Java 5
Version 5 of Java added three new thread-related packages: java.util.concurrent java.util.concurrent.atomic java.util.concurrent.locks The classes and interfaces in these packages provided high-quality, thread-safe building blocks for developing concurrent classes and applications. thread pools − task synchronization utilities thread-safe collections − a task scheduling framework semaphores − atomic variables locks − condition objects ©SoftMoore Consulting
5
Creating Threads Two ways to create a thread:
Create a class that implements the Runnable interface. public interface Runnable { void run(); } Extend the Thread class and override its run() method. If your class must subclass some other class (e.g., Applet), you will need to use the first alternative. Implementing the Runnable interface is the preferred way to create a thread. ©SoftMoore Consulting
6
Creating a Thread by Implementing the Runnable Interface
Threads Creating a Thread by Implementing the Runnable Interface Create a class that implements the Runnable interface, and place the code for the thread in the run() method. public class SimpleRunnable extends SomeClass implements Runnable { public SimpleRunnable() { } @Override public void run() { } } ©SoftMoore Consulting
7
Creating a Thread by Implementing the Runnable Interface (continued)
Threads Creating a Thread by Implementing the Runnable Interface (continued) Construct an object of the class. Runnable r = new SimpleRunnable(); Construct a Thread object from the Runnable object. Thread t = new Thread(r); Start the thread. t.start(); ©SoftMoore Consulting
8
Creating a Thread by Implementing the Runnable Interface (continued)
Threads Creating a Thread by Implementing the Runnable Interface (continued) Alternate steps 3 and 4 (added in Java 5) Obtain an Executor object (e.g., from java.util.concurrent.ExecutorService). Executor e = ...; // several choices in package // java.util.concurrent Execute the thread. e.execute(r); ©SoftMoore Consulting
9
Creating a Thread by Extending the Thread Class
Threads Creating a Thread by Extending the Thread Class public class SimpleThread extends Thread { public SimpleThread() ... } @Override public void run() // elsewhere (e.g., in another class) Thread t = new SimpleThread(); t.start(); This approach is no longer recommended. ©SoftMoore Consulting
10
Key Constructors and Methods in Class Thread
Threads Key Constructors and Methods in Class Thread Constructors public Thread() public Thread(Runnable target) Methods public void run() // called by JVM public void start() public static void sleep(long milliseconds) public static void yield() // use to prevent "starvation" public boolean isAlive() public void join() // waits for this thread to die public void join(long milliseconds) public static Thread currentThread() ©SoftMoore Consulting
11
Threads Deprecated Methods public void stop() public void suspend() public void resume() Note: These methods are inherently unsafe and have been deprecated. ©SoftMoore Consulting
12
Method sleep() in Class Thread
Threads Method sleep() in Class Thread The method sleep() causes the currently executing thread to sleep (temporarily cease execution) for the specified time, subject to limitations of the underlying operating system. Two versions public static void sleep(long millis) … public static void sleep(long milis, long nanos) … A call to sleep() with a value of 0 can be used to indicate that the thread is willing to relinquish the processor to other waiting threads. Calling method yield() is preferable to calling sleep(0) if a thread is willing to allow other waiting threads to execute. ©SoftMoore Consulting
13
Method Thread.sleep() (continued)
Constants can be used to improve readability private static final long MILLISECONDS = 1; private static final long SECONDS = 1000*MILLISECONDS; private static final long MINUTES = 60*SECONDS; ... Thread.sleep(50*MILLISECONDS); Thead.sleep(2*MINUTES + 30*SECONDS); ©SoftMoore Consulting
14
Example: Simple Thread
Threads Example: Simple Thread public class SimpleRunnable implements Runnable { private String message; public SimpleRunnable(String message) { this.message = message; } ©SoftMoore Consulting
15
Example: Simple Thread (continued)
Threads Example: Simple Thread (continued) @Override public void run() { for (int i = 0; i < 10; ++i) { System.out.println(i + " " + message); try { Thread.sleep((int)(Math.random()*100)); } catch (InterruptedException e) { ... } } } } ©SoftMoore Consulting
16
Example: Simple Thread (continued)
Threads Example: Simple Thread (continued) public class SimpleRunnableTest { public static void main (String[] args) Runnable r1 = new SimpleRunnable("Hello"); Runnable r2 = new SimpleRunnable("World"); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); } ©SoftMoore Consulting
17
Thread States A thread can be in one of the following states:
NEW − not yet started RUNNABLE − ready to run BLOCKED − waiting to acquire a lock WAITING − waiting indefinitely for another thread to perform a particular action TIMED_WAITING − waiting for another thread to perform an action for up to a specified waiting time TERMINATED − finished executing; e.g., run method has completed or uncaught exception has been raised method isAlive() returns true ©SoftMoore Consulting
18
Thread States Diagram BLOCKED NEW RUNNABLE WAITING Ready Running TIMED
IO complete or lock acquired NEW new() block on IO or wait for lock/synchronized block start() RUNNABLE WAITING processor available wait(), join(), park() Ready Running notify(), notifyAll() yield finished executing TIMED WAITING sleep(time), wait(time), join(time), park(time) TERMINATED time elapsed ©SoftMoore Consulting
19
Timed Loops – With Cumulative Drift
Threads Timed Loops – With Cumulative Drift while (true) { try … // actions Thread.sleep(30*SECONDS); } catch (InterruptedException ex) … Time to complete an iteration of the loop includes time to perform the actions. ©SoftMoore Consulting
20
Timed Loops – Avoiding Drift
Threads Timed Loops – Avoiding Drift private static final long INTERVAL = 30*SECONDS; private long nextTime = System.currentTimeMillis(); ... while (true) { try ... // actions nextTime = nextTime + INTERVAL; Thread.sleep(nextTime - System.currentTimeMillis()); } catch (InterruptedException ex) … ©SoftMoore Consulting
21
Example: Monitoring Water Temperature
Threads Example: Monitoring Water Temperature public class WaterTempMonitor extends Thread { private static final long INTERVAL = 5*SECONDS; public void run() long nextTime = System. currentTimeMillis(); while (true) if (getWaterTemperature() > MAX_TEMPERATURE) activateAlarm(); nextTime = nextTime + INTERVAL; Thread.sleep(nextTime – System.currentTimeMillis()); } ©SoftMoore Consulting
22
Threads Example: Monitoring Water Temperature (Using Java 8 Time-Related Classes) public class WaterTempMonitor extends Thread { private static final long INTERVAL = 5; // seconds public void run() private Instant nextTime = Instant.now(); while (true) if (getWaterTemperature() > MAX_TEMPERATURE) activateAlarm(): nextTime = nextTime.plusSeconds(INTERVAL); Duration dur = Duration.between(Instant.now(), nextTime); Thread.sleep(dur.toMillis()); } ©SoftMoore Consulting
23
Thread Names Threads have names Constructors and methods
no real semantics used for identification and debugging. Constructors and methods public Thread(String name) public Thread(Runnable target, String name) public void setName(String name) public String getName() Default name: “Thread-”<unique number> Name is returned by the toString() method ©SoftMoore Consulting
24
Threads Thread Priority Each thread has a priority. A higher value indicates a higher degree of urgency. Constants in class Thread public static final int MAX_PRIORITY // defined as 10 public static final int MIN_PRIORITY // defined as 1 public static final int NORM_PRIORITY // default (5) Methods public void setPriority(int newPriority) public int getPriority() Thread priorities are mapped to the priority levels of the host platform, which may have more or fewer priority levels; e.g., Windows has seven levels. ©SoftMoore Consulting
25
Thread Priority (continued)
Threads Thread Priority (continued) If two threads are in the ready state, the one with the highest priority will be selected to run. Caution: Improper use of thread priorities can result in “starvation” of threads with lower priorities. ©SoftMoore Consulting
26
Threads Thread Interaction Threads need to interact with each other for several reasons: Information Exchange Activity Synchronization to coordinate the activities of parallel threads executing asynchronously Mutual Exclusion to get exclusive access to a shared resource ©SoftMoore Consulting
27
Protecting Shared Resources
Threads Protecting Shared Resources Whenever several threads have access to a shared resource, we must maintain the integrity of the operations and data. Mutual exclusion means that only one thread of control can operate upon that resource at a time – multiple threads of control are serialized. In order to prevent simultaneous updates by different threads, we must provide exclusive access to a shared resource. “The basic concurrent programming problem is mutual exclusion.” – M. Ben-Ari ©SoftMoore Consulting
28
The Need for Mutual Exclusion
public void transfer(Account from, Account to, Double amount) { from.debit(amount); to.credit(amount); } Recall that each Java statement is translated into multiple JVM instructions. Consider what could happen if two threads are simultaneously trying to update the same account, and the first thread is preempted before completing the transfer() method. ©SoftMoore Consulting
29
Synchronization Locks Synchronization is based on locks.
Threads Synchronization Locks Since version 1.0, every object in Java has an intrinsic lock. Java 5.0 added additional lock classes such as ReentrantLock and ReadWriteLock. Synchronization is based on locks. Synchronized code is atomic – only one thread at a time can execute the synchronized code. ©SoftMoore Consulting
30
Synchronization (continued)
Threads Synchronization (continued) Synchronized methods public synchronized void someMethod() { ... // statements } Synchronized block of code ... // statements synchronized(someObject) ... // statements } Note: someObject is often this or an object created specifically for use as a lock. ©SoftMoore Consulting
31
Waiting and Notification
Threads Waiting and Notification It is possible for a thread to “wait” for some condition to occur. Another thread can then “notify” the waiting thread that the condition has occurred. Primitive methods inherited from class Object wait() wait(long timeout) notify() notifyAll() ©SoftMoore Consulting
32
Example: Waiting and Notification
Threads Example: Waiting and Notification public synchronized void getResource(int numberToGet) { while (true) if (resourceCount > numberToGet) resourceCount -= numberToGet; break; } try wait(); catch (Exception e) ©SoftMoore Consulting
33
Example: Waiting and Notification (continued)
Threads Example: Waiting and Notification (continued) public synchronized void freeResource(int numberToFree) { resourceCount += numberToFree; notifyAll(); } ©SoftMoore Consulting
34
Using Waiting and Notification
Threads Using Waiting and Notification Must be used in conjunction with synchronization The thread calling methods wait(), notify(), etc. must hold locks for the object for which they are waiting or notifying. The wait() method releases the lock prior to waiting and reacquires it prior to returning from the wait() method. Note: Methods wait(), notify(), etc. have been part of Java since the 1.0 release, but this functionality has essentially been replaced by explicit locks and methods await(), signal(), signalAll(), etc. ©SoftMoore Consulting
35
Threads Race Conditions A race condition is a set of circumstances in which the relative speeds of two threads can influence the result of program execution. It can occur when two concurrent threads operate on a shared resource in overlapping time intervals. Example thread1 if (!stack.isEmpty()) x = stack.pop(); thread2 if (!stack.isEmpty()) x = stack.pop(); time ©SoftMoore Consulting
36
Race Conditions (continued)
Threads Race Conditions (continued) Race conditions typically have irreproducible results, making the construction of reliable concurrent systems difficult. ©SoftMoore Consulting
37
Threads Deadlock Deadlock is the situation in which one or more threads become permanently blocked waiting for resources that will never become available. Example thread1 synchronize(resource1) { synchronize(resource2) { } } thread2 synchronize(resource2) { synchronize(resource1) { } } time ©SoftMoore Consulting
38
Deadlock (continued) Conditions for deadlock Reasons for deadlock
Threads Deadlock (continued) Conditions for deadlock mutual exclusion partial resource allocation nonpreemptive scheduling circular waiting Reasons for deadlock poor program design occurrence of unanticipated events ©SoftMoore Consulting
39
Threads Deadlock Avoidance Ensure that the four conditions necessary for deadlock are not satisfied at the same time Strategies grant permission for using both (all) resources simultaneously, instead of one at a time require a thread to give up its resources temporarily order the resources; e.g., each thread must get permission for resource1 first and then for resource2, to avoid the circular-wait problem ©SoftMoore Consulting
40
Threads Thread Interruption It is possible for one thread to immediately signal another thread. analogy with a call on your cell phone An interrupt signals the thread to stop doing what it is currently doing and do something else. Associated methods void interrupt() Interrupts this thread. static boolean interrupted() Tests whether the current thread has been interrupted. ©SoftMoore Consulting
41
Effect of Interrupting a Thread
Threads Effect of Interrupting a Thread If the interrupted thread is executing a wait(), sleep(), or join() method, that method will throw an InterruptedException. The interrupted thread moves to an unblocked state. Otherwise, a flag is set that can be tested via the interrupted() method. Many methods that throw InterruptedException (e.g., sleep()) are designed to cancel their current operation and return immediately when an interrupt is received. ©SoftMoore Consulting
42
Terminating a Thread The normal way for a thread to terminate is for the run() method to return after it has finished. To “force” termination of a running thread, call its interrupt() method, which will set a boolean flag in the thread indicating that it should terminate. t.interrupt(); A thread can check to see if the flag has been set by calling the static method interrupted(), which returns the value of the boolean flag. ©SoftMoore Consulting
43
Terminating a Thread (continued)
Calling the interrupt() method allows the interrupted thread to release any resources it is currently using and perform other required cleanup before terminating; i.e., the thread is in charge of terminating itself. Class Thread also contains a method stop() that will immediately terminate a thread, but this method has been shown to be inherently unsafe and is now deprecated. Do not call method stop() on a thread. ©SoftMoore Consulting
44
Threads Daemon Threads A daemon thread is a thread whose purpose is to serve “user” threads. During thread scheduling, if only daemon threads remain, the program will terminate. Example: the garbage collector thread Relevant methods void setDaemon(boolean on) boolean isDaemon() The setDaemon() method must be called before the thread has been started. ©SoftMoore Consulting
45
Threads Explicit Locks A lock is a tool for controlling access to a shared resource by multiple threads. Commonly, a lock provides exclusive access only one thread at a time can acquire the lock, and all access to the shared resource requires that the lock be acquired first Some locks may allow concurrent access to a shared resource, such as the read lock of a ReadWriteLock. Explicit locks are provided in package java.util.concurrent.locks ©SoftMoore Consulting
46
The Lock Interface package java.util.concurrent.locks;
Threads The Lock Interface package java.util.concurrent.locks; public interface Lock { public void lock(); public void lockInterruptibly(); public Condition newCondition(); public boolean tryLock(); public boolean tryLock(long time, TimeUnit unit); public void unlock(); } ©SoftMoore Consulting
47
The ReadWriteLock Interface
Threads The ReadWriteLock Interface package java.util.concurrent.locks; public interface ReadWriteLock { public Lock readLock(); public Lock writeLock(); } A ReadWriteLock maintains a pair of associated locks one for read-only operations one for writing Permits multiple concurrent readers but only one writer. ©SoftMoore Consulting
48
Lock Implementations ReentrantLock implements Lock
Threads Lock Implementations ReentrantLock implements Lock thread can repeatedly acquire a lock that it already owns (can call another method that uses the same lock) must call unlock() for every call to lock() lock keeps track of nested calls to the lock() method ReentrantReadWriteLock implements ReadWriteLock reentrant (see above) If readers are active and a writer enters the lock, then no subsequent readers will be granted the read lock until after that writer has acquired and released the write lock. supports an optional fairness policy, where threads contend for entry using an approximately arrival-order policy ©SoftMoore Consulting
49
Threads Using Explicit Locks An explicit lock is more flexible than using synchronized blocks and methods since locks can span a few statements in a method or calls to multiple methods. Must ensure that the lock is released Lock l = ...; // usually a ReentrantLock l.lock(); try { // critical section // access the resource protected by this lock } finally l.unlock(); ©SoftMoore Consulting
50
Package java.util.concurrent.atomic
The package java.util.concurrent.atomic contains several classes that support lock-free thread-safe programming on single variables. AtomicBoolean − AtomicInteger AtomicIntegerArray − AtomicLong LongAdder − ... Methods calls on instances of these classes are atomic; i.e., the calls are thread-safe without using the synchronized keyword or locks. Internally, the atomic classes use atomic instructions directly supported by most modern CPUs, so they are usually much faster than synchronizing via locks. ©SoftMoore Consulting
51
Threads Condition Objects A lock object can have one or more associated condition objects. Lock l = new ReentrantLock(); Condition needResource = lock.newCondition(); If a thread has acquired a lock but then discovers that it can’t continue until a certain condition is met, it can indicate that it is willing to wait on that condition using one of several Condition.await methods. When a thread performs an action that satisfies a condition, it can notify waiting threads that the condition has been met by calling one of two Condition.signal methods. ©SoftMoore Consulting
52
Condition Await Methods
Threads Condition Await Methods Method Description await() Wait until signaled or interrupted await(long, TimeUnit) Wait until signaled or interrupted, or the specified waiting time elapses awaitNanos(long) awaitUninterruptibly() Wait until it is signaled awaitUntil(Date) Wait until signaled or interrupted, or the specified deadline elapses ©SoftMoore Consulting
53
Condition Signal Methods
Threads Condition Signal Methods Method Description signal() Wakes up one waiting thread. signalAll() Wakes up all waiting threads. Usually you should call signallAll(). It is slightly less efficient, but it is also less prone to deadlock. ©SoftMoore Consulting
54
Example: Condition Objects
Threads Example: Condition Objects public class BoundedBuffer { Lock lock = new ReentrantLock(); Condition notFull = lock.newCondition(); Condition notEmpty = lock.newCondition(); public void put(Object x) throws InterruptedException lock.lock(); try while (count == items.length) notFull.await(); … // add x to the buffer notEmpty.signalAll(); } finally lock.unlock(); ©SoftMoore Consulting
55
Example: Condition Objects (continued)
Threads Example: Condition Objects (continued) public Object get() throws InterruptedException { lock.lock(); try while (count == 0) notEmpty.await(); … // remove x from the buffer notFull.signalAll(); return x; } finally lock.unlock(); Note: Class ArrayBlockingQueue provides the functionality illustrated by this example. ©SoftMoore Consulting
56
Blocked by a Lock versus Blocked Awaiting a Condition
Threads Blocked by a Lock versus Blocked Awaiting a Condition There is a difference between a thread that is blocked while waiting to acquire a lock and a thread that has called await(). When a thread calls await(), it enters a wait set for that condition. The thread is not unblocked when the lock is available. Instead, it stays blocked until another thread calls signal() or signalAll() on the same condition. ©SoftMoore Consulting
57
Thread Groups A ThreadGroup class manages a group of related threads.
ThreadGroup group = new ThreadGroup(groupName); Thread t = new Thread(group, r); A thread group can contain not only threads but also other thread groups (similar to directories). The top most thread group is named “main”. Class ThreadGroup contains several methods that can be used to manage the contained threads and groups; e.g., it is possible to set the name for the group, to get an array of all threads in the group, and to set the priority for the entire group. ©SoftMoore Consulting
58
Concurrent Collections (in java.util.concurrent)
Threads Concurrent Collections (in java.util.concurrent) Interfaces BlockingDeque BlockingQueue ConcurrentMap Implementations (classes) ArrayBlockingQueue ConcurrentHashMap ConcurrentLinkedQueue CopyOnWriteArrayList CopyOnWriteArraySet LinkedBlockingDeque LinkedBlockingQueue PriorityBlockingQueue ©SoftMoore Consulting
59
Buffered Communication
Threads Buffered Communication Buffering can be used to smooth out variations in speeds of two communicating threads. With a large enough buffer, the actual data flow will approximate the average data flow. Java provides blocking queues for buffering communication between threads. A blocking queue causes a thread to block when trying to add an element to a full queue when trying to remove an element from an empty queue Often one thread writes to the queue while another thread reads from the queue. ©SoftMoore Consulting
60
Interface BlockingQueue
Threads Interface BlockingQueue Three categories of methods based on response to failure (e.g., attempting to add an element to a full queue or remove an element from an empty queue) Methods that throw an exception add() remove() element() Methods that return a value indicating failure offer() poll() peek() Methods that block put() take() Implemented by several classes ArrayBlockingQueue – PriorityBlockingQueue LinkedBlockingQueue – etc. ©SoftMoore Consulting
61
Asynchronous Communication
Threads Asynchronous Communication Asynchronous communication between two threads can be achieved by defining a third thread as a mailbox. Example public class MailBox { public synchronized void write(String message) {...} public synchronized String read() {...} // other implementation details } Mailboxes could be created dynamically as needed. A blocking queue could be used to implement the mailbox. thread 1 mailbox thread 2 ©SoftMoore Consulting
62
Thread Safety (Brian Goetz)
A class is thread-safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code. Writing thread-safe code is about managing access to shared, mutable state, where an object’s state is its data. Thread-safe classes encapsulate any needed synchronization so that clients need not provide their own. ©SoftMoore Consulting
63
Threads More on Thread Safety Stateless objects and immutable objects are always thread-safe. Parameters and local variables (declared within a method) are stored on the run-time stack, and each thread has its on stack. A method that uses only local variables or parameters is always thread safe as long as it doesn’t use parameters to modify mutable objects. An object that is accessed by only one thread need not be thread-safe. simpler, better performance but … are you sure that it never will be accessed by multiple threads? ©SoftMoore Consulting
64
Levels of Thread Safety (Joshua Bloch)
Immutable Unconditionally thread-safe class has sufficient internal synchronization Conditionally thread-safe some methods require external synchronization Not thread-safe require external synchronization examples: ArrayList and HashMap Thread-hostile usually not-intentional example: System.runFinalizersOnExit() method ©SoftMoore Consulting
65
Guidelines for Effective Java (Joshua Bloch)
Threads Guidelines for Effective Java (Joshua Bloch) Synchronize access to shared mutable data Synchronization is required for reliable communication between threads as well as for mutual exclusion. Avoid excessive synchronization As a rule, do as little work as possible inside synchronized regions. Prefer executors to tasks and threads (More on this when we study networking.) Prefer concurrency utilities to wait and notify e.g., use ConcurrentHashMap in preference to Collections.synchronizedMap or Hashtable Document thread safety ©SoftMoore Consulting
66
Recommendations (Horstmann and Cornell)
Threads Recommendations (Horstmann and Cornell) It is best to use neither Lock/Condition nor the synchronized keyword. In many situations you can use one of the mechanisms of the package java.util.concurrent (e.g., BlockingQueue) that do all the locking for you. If the synchronized keyword works for your situation, then use it. less code to write less room for error Use Lock/Condition if you specifically need the additional power that these constructs provide. ©SoftMoore Consulting
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.