Transcript 07_Threads

Threads
Doing Several Things at Once
Threads
What are Threads?
 Two Ways to Obtain a New Thread
 The Lifecycle of a Thread
 Four Kinds of Thread Programming

What are Threads?

A Thread is a unit of program execution that
runs independently from other threads.
- lightweight process



Threads behave as if they were running on
different CPUs
Extend the concept of time-sharing.
Garbage collectors and listeners run in
separate threads
Thread Context
Context switched when JVM switched to
a different thread
 Not as costly as switching processes
 Threads can make a program run faster
 Threads allow a program to do more
that one thing at a time

- one processor?
• the system handles the sharing
Two Ways to Obtain a New
Thread

Extend the java.lang.Thread Class

Implement the “Runnable” interface
- Applets extend the class Applet by
definition.
 an applet must always use the second
technique; extends is taken by (J)Applet
Extension of
java.lang.Thread






Create a class extending Thread Class
Put the code for the task into the run
method of the new class
Create an instance of that class
Call the start method for that instance
The start method will call the run method
The thread executes until the run method
terminates.
Extending the Thread Class
Class AThread extends Thread
{
…
public void run()
{
// your code here
}
}
Running a Thread

In another thread, create the thread
AThread t1 = new AThread();

Start the thread by calling its start method
t1.start();



The call to start creates and schedules the
thread to execute. The run method is called
by the JVM when it is the thread’s turn to
execute
See Java Documentation on Thread
See:
- NameThread.java
- ThreadTest.java
The Runnable Interface
public interface Runnable
{
// Must write run()
public abstract void run();
}
Implement Runnable

Create a class ARunnable which implements the
“runnable” interface.
public class ARunnable implements Runnable
{
public void run() { … }
}

Use that class in a call to the Thread constructor
Thread t = new Thread( new ARunnable() );
t.start(); // start the thread


See Java Doc on Runnable
See NameUsingThread.java
Notes on Runnable

Statements within the Runnable
Interface implementation of run() can’t
invoke Thread methods like “sleep()”,
“getName()”, etc. because no “this”
object is available in Runnable.
- the object isn’t the thread
Remarks


A call to currentThread() can appear
anywhere in Java code. Any of the methods
of that thread can be called via the thread
returned in currentThread().
Runnable vs Thread: Use Runnable when
only the “run()” method will be overridden.
Classes should not be extended unless there
is a fundamental enhancement of behavior.
Terminating Threads
A thread terminates when its run
method returns – the normal way
 A thread can be interrupted (never
stopped) by using the thread.interrupt()
method.
 A thread’s run method should
occasionally check for the interrupt
signal

Interrupt Coding
public void run()
{
try // DO NOT PUT try in a loop, but loop in try
{ // do some work
}
catch (InterruptedException e)
{ // do whatever needs to be done
}
// clean up
}
Parameters to Threads
The run method cannot have
parameters
 The constructor can have parameters
 The Thread constructor can have
certain parameters

- see API for java.lang.Thread
Thread Lifecycle
A thread is created, then “started”
 The thread “dies” when

- The run method terminates:
• normally
• through an exception or return
- A thrown exception will cause the thread to
terminate but not the parent
Priorities



A thread runs at the priority of its parent unless its
priority is changed.
A higher priority executes first if they are both
ready to run
Java threads
- can be preempted.
- may or may not be time-sliced


Computationally intensive threads should “yield”
periodically
Raising a thread’s priority does not affect other
(heavyweight) processes, only parent, sibling,
children threads (competing lightweight processes)
Four Kinds of Thread
Programming
1.
2.
3.
4.
Unrelated Threads
Related Unsynchronized Threads
Mutually-Exclusive Threads
Communicating Mutually-Exclusive
Threads
Thread Diagram
A Class
An Object has Methods
An Object
An Object
An Object has Methods
Thread runs in a method
Unrelated Threads
The simplest thread programs involves
threads that do different things
 Don’t interact with one another
 Coffee_Tea Example

- Change sleep time; run on PC and Suns to
see difference
Related, Unsynchronized
Threads




The problem is partitioned into subproblems
A thread solves each subproblem
The threads don’t interact
They don’t work on shared data
- Example: testPrime.java


A server connection for each socket
connection is a good example
A “Work-to-order” thread is called a daemon
- always on
Mutally-Exclusive Threads
Threads that access common data
concurrently need to be controlled so
that the correct state of the data is
preserved at all times. Such a situation
occurs frequently in the real world.
The Pressure Gauge
Consider reading and setting a pressure
gauge. The gauge should not be set
above 20 psi. But the pressure is set by
pressure setting objects, independent of
one another. Each must check the
gauge and if it is safe to do so, increase
the pressure by a fixed amount.
- Example:
• BadPressure.java
BadPressure output
>java BadPressure
Gauge reads 150, safe limit is 20
What happened?
- code appeared to restrict gauge value, but didn’t
• Setting the gauge is a critical section
– Mutual exclusion required
Mutual Exclusion

Simultaneous reading and setting of the
pressure gauge by different threads
- set followed check; all did check, THEN did
change
• check-change must be atomic
one object needs to lock others out until
it is finished
 can be done at the class level, method
level, or on a block of code

The keyword synchronized
This keyword obtains a mutex (mutual
exclusion) lock for the executing thread
on the named object. The code is then
executed, and the lock is released. If
another object already holds the lock,
the thread is suspended until the lock is
released. Lock-competing threads are
queued.
Some considerations

Java programmers don’t need to do the
low level details of creating, acquiring,
and releasing locks
- Unix semaphores, locks
Specify the portion of code (critical
section) for mutual exclusion, and the
object that must be exclusively locked
 The region of code must be as small as
possible

Mutual Exclusion over an Entire Class

apply the keyword synchronized to a class method.
- e.g. static synchronized void RaisePressure()



Only one static synchronized method for a given class can
be running at any given time in the JVM, regardless of
how many objects there are of that class
the class object is used to synchronize the threads
There is one lock for static synchronized methods, and a
different lock for synchronized methods. One thread could
have the static lock while another thread has a method
lock, while other threads could be running other
unsynchronized methods
- Example: SetPressure.java
Class Mutual Exclusion

From SetPressure.java
// Only one thread may be executing in here
static synchronized void raisePressure()
{ if(BadPressure.pressureGauge <
BadPressure.SafetyLimit - 15)
{
....
>java SetPressure
Gauge reads 15, safe limit is 20
Mutual Exclusion over a Block
use the keyword synchronized before a
block of code
 Use a static object for the lock
 any available, convenient object will do
 cannot be a local object or instance
variable

Block Mutual Exclusion
class pressure extends Thread
{ static Object lock = new Object();
void raisePressure()
{
synchronized(lock); Mutex ‘til end
{
if(SetPressure.pressureGauge <
SetPressure.SafetyLimit - 15)
{
...
}
...
}
Mutual Exclusion over a Method



use synchronized keyword on the instance
method.
guarantees that only one of the perhaps
many synchronized instance methods will be
executing at any one time on a given instance
of that class
equivalent to synchronized(this) over a block
- Examples:
• raisePressure
• Monitor in MessagePass.java
Method Synchronization
synchronized void raisePressure()
{
if(p.pressureGauge <
p.SafetyLimit - 15)
{
...
same as
void raisePressure()
{
synchronized(this) // on this object
{
if(p.pressureGauge < p.SafetyLimit - 15)
{ ...
}
}
Communicating Mutually
Exclusive Threads





Threads that need to access common data,
but also communicate with one another
the hardest kind of thread programming
Producer/Consumer type of problem
I produce, you consume. Don’t try to produce
until there is something to consume. Don’t
produce too much, until something is
consumed
Wait/Notify is the solution
Wait / Notify
Wait says “I have the lock, but there is
nothing to consume. I give up the lock
and wait
 Notify says “I just produced something,
I will place it in common area, release
the lock and wait”

Producer Pseudo-code
// producer thread
enter synchronized code // get lock
while(buffer_full)
wait();
produce_items()
notify() // tell waiting consumers
leave synchronized code // release lock
consumerPseudo-code
// consumer thread
enter synchronized code // get lock
while(no_items)
wait();
consume_items()
leave synchronized code
Notes:

Examples
- plum.java
• inelegant dependant producer-consumer
- Operator Examples
• MessagePass.java
– Operator with Monitor
• Operator.java
– Operator w/o monitor (inelegant, too)
- Tally Examples
• TallyWrong.java
• TallyRight.java
– Note how inner classes compile
- PutGet.java
• vary relative wait times and see what happens
- Deadlock.java
• oh, oh; somewhat inelegant – works with zero buffer
Examples, etc;

CommunicatingThreads.java
- applet with piped communication
between two threads

Exercise
- Try the PutGet example with multiple
producers/consumers. Change the
constructors so that you know who is
producing what and who is consuming
what.