Threads
Java Threads
• A thread is not an object
• A thread is a flow of control
• A thread is a series of executed statements
• A thread is a nested sequence of method
calls
The Thread Object
• A thread is not an object
• A Thread is an object
void start()
– Creates a new thread and makes it runnable
void run()
– The new thread begins its life inside this
method
Thread Creation Diagram
Object A Object BThread (extends Thread)
BThread() {
}
Thread t = new BThread();
void start() {
t.start(); // create thread
}
doMoreStuff();
void run() {
doSomething();
}
Thread Creation Diagram
Object A Object BThread (extends Thread)
BThread() {
}
Thread t = new BThread();
void start() {
t.start(); // create thread
}
doMoreStuff();
void run() {
doSomething();
}
Thread Creation Diagram
Object A Object BThread (extends Thread)
BThread() {
}
Thread t = new BThread();
void start() {
t.start(); // create thread
}
doMoreStuff();
void run() {
doSomething();
}
Thread Creation Diagram
Object A Object BThread (extends Thread)
BThread() {
}
Thread t = new BThread();
void start() {
t.start(); // create thread
}
doMoreStuff();
void run() {
doSomething();
}
Thread Creation Diagram
Object A Object BThread (extends Thread)
BThread() {
}
Thread t = new BThread();
void start() {
t.start(); // create thread
}
doMoreStuff();
void run() {
doSomething();
}
Thread Creation Diagram
Object A Object BThread (extends Thread)
BThread() {
}
Thread t = new BThread();
void start() {
t.start(); // create thread
}
doMoreStuff();
void run() {
doSomething();
}
Thread Creation Diagram
Object A Object BThread (extends Thread)
BThread() {
}
Thread t = new BThread();
void start() {
t.start(); // create thread
}
doMoreStuff();
void run() {
doSomething();
}
Thread Creation Diagram
Object A Object BThread (extends Thread)
BThread() {
}
Thread t = new BThread();
void start() {
t.start(); // create thread
}
doMoreStuff();
void run() {
doSomething();
}
Thread Creation Diagram
Object A Object BThread (extends Thread)
BThread() {
}
Thread t = new BThread();
void start() {
t.start(); // create thread
}
doMoreStuff();
void run() {
doSomething();
}
Runnable Interface
• A helper to the thread object
• The Thread object’s run() method calls the
Runnable object’s run() method
• Allows threads to run inside any object,
regardless of inheritance
Runnable Example
Talker talker = new Talker();
Thread t = new Thread(talker);
t.Start();
---
class Talker implements Runnable {
public void run() {
while (true) {
System.out.println(“yakitty yak”);
}
}
}
Thread Lifecycle
Active sleep(500)
wake up
JVM
Born start()
suspend()
resume()
Runnable
Blocked
stop() wait
stop()
notify
block on I/O
Dead
I/O available
Blocking Threads
• When reading from a stream, if input is not
available, the thread will block
• Thread is suspended (“blocked”) until I/O is
available
• Allows other threads to automatically activate
• When I/O available, thread wakes back up again
– Becomes “runnable”
– Not to be confused with the Runnable interface
Thread Scheduling
• In general, the runnable thread with the
highest priority is active (running)
• Java is priority-preemptive
– If a high-priority thread wakes up, and a low-
priority thread is running
– Then the high-priority thread gets to run
immediately
• Allows on-demand processing
– Efficient use of CPU
Thread Starvation
• If a high priority thread never blocks
• Then all other threads will starve
• Must be clever about thread priority
Thread Priorities: General
Strategies
• Threads that have more to do should get lower
priority
• Counterintuitive
• Cut to head of line for short tasks
• Give your I/O-bound threads high priority
– Wake up, immediately process data, go back to
waiting for I/O
Race Conditions
• Two threads are simultaneously modifying
a single object
• Both threads “race” to store their value
• In the end, the last one there “wins the race”
• (Actually, both lose)
Race Condition Example
class Account {
int balance;
public void deposit(int val)
{
int newBal;
newBal = balance + val;
balance = newBal;
}
}
Thread Synchronization
• Language keyword: synchronized
• Takes out a monitor lock on an object
– Exclusive lock for that thread
• If lock is currently unavailable, thread will
block
Thread Synchronization
• Protects access to code, not to data
– Make data members private
– Synchronize accessor methods
• Puts a “force field” around the locked
object so no other threads can enter
• Actually, it only blocks access to other
synchronizing threads
Thread Deadlock
• If two threads are competing for more than
one lock
• Example: bank transfer between two
accounts
– Thread A has a lock on account 1 and wants to
lock account 2
– Thread B has a lock on account 2 and wants to
lock account 1
Avoiding Deadlock
• No universal solution
• Ordered lock acquisition
• Encapsulation (“forcing directionality”)
• Spawn new threads
• Check and back off
• Timeout
• Minimize or remove synchronization
Wait and Notify
• Allows two threads to cooperate
• Based on a single shared lock object
Wait and Notify: Code
• Consumer:
synchronized (lock) {
while (!resourceAvailable()) {
lock.wait();
}
consumeResource();
}
Wait and Notify: Code
• Producer:
produceResource();
synchronized (lock) {
lock.notifyAll();
}
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify Sequence
Lock Object
1. synchronized(lock){ 3. produceResource()
2. lock.wait(); 4. synchronized(lock)
5. lock.notify();
9. consumeResource();
10. } 6.}
7. Reacquire lock
8. Return from wait()
Consumer Producer
Thread Thread
Wait/Notify: Details
• Often the lock object is the resource itself
• Sometimes the lock object is the producer
thread itself
Wait/Notify: Details
• Must loop on wait(), in case another thread
grabs the resource...
– After you are notified
– Before you acquire the lock and return from
wait()
• Use lock.notifyAll() if there may be more
than one waiting thread
Wait/Notify Example: Blocking
Queue
class BlockingQueue extends Queue {
public synchronized Object remove() {
while (isEmpty()) {
wait(); // really this.wait()
}
return super.remove();
}
public synchronized void add(Object o) {
super.add(o);
notifyAll(); // this.notifyAll()
}
}