Title: Threads
1Threads
- HY556 Distributed Systems
- Computer Science Department
- University of Crete
2What is a Thread
- A single sequential flow of control within a
program. - Similar to sequential programs
- Single thread
- a beginning
- a sequence
- an end
- At any given time during the runtime of the
thread ? - a single point of execution.
- A thread itself is not a program ? it cannot run
on its own. - A thread runs within a program.
3What is a Thread (cont.)
- Thread lightweight process execution
context. - Similar to a real process both are a single
sequential flow of control. - A thread runs within the context of a full-blown
program ? takes advantage of the resources
allocated for that program - As a sequential flow of control, a thread must
carve out some of its own resources within a
running program. - e.g. it must have its own execution stack and
program counter
4What is a Thread (cont.)
- Early days of computing, computers ? single
tasking - Run a single process at a time.
- Multitasking
- Computers capability to perform multiple jobs
concurrently (e.g. operating system). - Multithreading
- Extension of the multitasking paradigm.
- Involves multiple threads of control within a
single program. - Threads ? subprograms within the program.
5What is a Thread (cont.)
- class MainIsRunInAThread
- public static void main(String args)
- // main() is run in a single thread
- System.out.println(Thread.currentThread())
- for (int i 0 i lt 1000 i)
- System.out.println(i i)
-
-
6What is a Thread (cont.)
- Previous simple example
- demonstrating the use of a single Java thread.
- When the Java application begins
- the VM runs the main() method inside a Java
thread. - Example shown
- counts from 0 to 999 printing out each value as
it is counted, within this single thread. - Programming within a single sequence of control
can limit your ability to produce usable
software. - E.g. an operating system that could execute only
one program at a time.
7What is a Thread (cont.)
class CountThreadTest extends Thread int from,
to public CountThreadTest(int from, int to)
this.from from this.to to // the
run() method is like main() for a thread public
void run() for (int i from i lt to i)
System.out.println(i i)
8What is a Thread (cont.)
public static void main(String args) //
spawn 5 threads, each of which counts 200
numbers for (int i 1 i lt 5 i)
CountThreadTest t new CountThreadTest(i200
, (i1)200) // starting a thread will launch
a separate sequence // of control and execute
the run() method of the thread t.start()
// end class CountThreadTest
9What is a Thread (cont.)
- Modification of the previous example to take
advantage of threads. - Use 5 different threads to count from 0 to 999,
each of them counts 200 numbers. - The VM invokes the main() method in its own
thread. - main() then starts 5 separate threads to perform
the counting operation.
Parallel Java threads
10What is a Thread (cont.)
- NOTE
- Multiple threads may appear to perform tasks at
the same time. - Technically may not be true.
- Even today, most computers are equipped with a
single processor ? such computers can perform at
most one task at a time. - On single-processor systems, the OS continuously
switches between different tasks and threads,
allowing each active task or thread to use the
CPU for a small amount of time.
11Java Threads
- Threads are not a Java invention.
- Use of Java threads ? no worry about which
threading packages are available for the
underlying platform or whether the OS supports
kernel threads. - The VM isolates you from the platform specific
threading details. - The Java threading API is identical on all Java
implementations.
12Creating New Threads
- Creating and running a thread ? 2 step procedure
- writing the code that is executed in the thread
- writing the code that starts the thread
- Provide a method that implements the main logic
of the thread, always named run() - public void run()
- run() is not a static method (as it is main()).
- main() is static because an application starts
with only one main() method. - An application may have many threads ?
- the main logic for a thread is associated with an
object the Thread object. - Provide an implementation for the run() method in
2 ways - Subclassing the Thread class.
- Implementing the Runnable interface.
13Subclassing the Thread Class
- Subclass java.lang.Thread (itself a Runnable
object) and override its empty run() method.
Example
public class SimpleThread exetnds Thread
public SimpleThread(String str)
super(str) public void run() for (int
i 0 i lt 3 i) System.out.println(i
getName()) try sleep((long)Math.random
()1000) catch (InterruptedException e)
System.out.println(DONE!
getName())
14Subclassing Thread (cont.)
public class TwoThreadDemo public static void
main(String args) new SimpleThread(Pass_HY5
56).start() new SimpleThread(Fail_HY556).sta
rt()
- Output
- 0 Pass_HY556
- 0 Fail_HY556
- 1 Fail_HY556
- 1 Pass_HY556
- 2 Fail_HY556
- DONE! Fail_HY556
- 2 Pass_HY556
- DONE! Pass_HY556
15Implementing Runnable
- Situations in which it is not convenient to
create a Thread subclass. - E.g. add a run() method to a preexisting class
that does not or cannot inherit from Thread - Java threading API supports the notion of a
thread-like entity that is an interface
java.lang.Runnable
public class MyClass extends MySuperClass
implements Runnable public void run()
16Thread States
- Java thread ? represented by a Thread object ?
life cycle
17Thread States (cont.)
- NEW
- When a Thread object is first created.
- The Thread is not executing !
- RUNNABLE
- When the Threads start() method is invoked.
- Thread is eligible for execution.
- Thread is not necessarily running but is alive
and it can be allocated CPU time by the system
when the CPU is available.
18Thread States (cont.)
- NOT RUNNABLE
- Thread is still alive but not eligible for
execution. - Thread is not allocated time on the CPU.
- Events that cause this state waiting for an I/O
operation to complete, calling sleep(), wait(),
suspend() methods. - DEAD
- Thread terminates.
- Usually run() method returns.
- Calling stop(), destroy() methods.
- A dead thread is permanently dead. There is no
way to resurrect a dead thread !
19Thread States (cont.)
- NOTE
- When a thread dies, all the resources consumed by
the thread, including the Thread object itself,
become eligible for reclamation by the garbage
collector (if, of course, they are not referenced
elsewhere). - Programmers are responsible for cleaning up
system resources (e.g. closing open files,
disposing of graphics contexts, and so on) while
a thread is terminating. - No cleanup is required after a thread dies.
20The Thread API
public Thread() public Thread(Runnable
target) public Thread(Runnable target, String
name) public Thread(String name) public
Thread(ThreadGroup group, Runnable
target) public Thread(ThreadGroup group,
Runnable target, String name) public
Thread(ThreadGroup group, String name)
21The Thread API (cont.)
- Constructors (cont.)
- name is the (string) name to be assigned to the
thread. If you fail to specify a name the system
generates a unique name of the form Thread-N, N a
unique integer. - target is the Runnable instance whose run()
method is executed as the main method of the
thread. - group is the ThreadGroup to which the thread will
be added. - Note although it is possible to allocate a
thread using new Thread(), it is not useful to do
so. When constructing a thread directly (without
subclassing), the Thread object requires a target
Runnable object because the Thread class itself
does not contain your applications logic.
22The Thread API (cont.)
public final String getName() public final void
setName(String name)
- Names are important because they provide the
programmer with a useful way to identify
particular threads during debugging. - Name a thread in such a way that you and others
can identify the purpose or function of the
thread.
23The Thread API (cont.)
public void start() public final void
stop() public final void stop(Throwable
obj) public void destroy() // not implemented
yet (even in v. 1.3)
- An exception is thrown when start() is called
more than once on the same thread. - stop() method causes that the thread terminates
by throwing a ThreadDeath exception to the
thread. Deprecated. Should be replaced by code
(e.g. modifying some variables) that indicates
that run() should return.
24The Thread API (cont.)
- Scheduling and Priority
- Scheduling the mechanism used to determine how
RUNNABLE threads are allocated CPU time. - Scheduling
- Preemptive the thread scheduler preempts
(pauses) a running thread to allow different
threads to execute. - Nonpreemptive the thread scheduler never
interrupts a running thread it relies on the
running thread to yield control of the CPU (!
starvation of other threads). - Preemptive
- Time-sliced the scheduler allocates a period of
time for which each thread can use the CPU. - Nontime-sliced the scheduler uses criteria to
determine when to preempt a thread, e.g. priority
or I/O status.
25The Thread API (cont.)
public final static int MAX_PRIORITY 10 public
final static int MIN_PRIORITY 1 public final
static int NORM_PRIORITY 5 public final int
getPriority() public final void setPriority(int
new_priority)
- Every thread has a priority.
- When a thread is created it inherits the priority
of the thread that created it. - Symbolic constants that represent the range of
priority from 1 to 10. An exception is thrown if
you attempt to set priority values outside this
range.
26The Thread API (cont.)
public void interrupt() public static boolean
interrupted() public boolean isInterrupted()
- interrupt() sends a wake-up message to a thread,
causes an InterruptedException to be thrown in
the thread and sets a flag that can be checked by
the running thread. - interrupted() checks the interrupt status of the
current thread and resets the interrupt status to
false. - isInterrupted() checks whether this thread has
been interrupted. The interrupt status of the
thread remains unaffected.
27The Thread API (cont.)
- Suspending and Resuming Thread Execution
public final void suspend() public final void
resume()
- suspend() pauses a thread, ensures that the
thread will not be run. - resume() reverses the suspend() operation.
- A call to suspend() puts the thread in the NOT
RUNNABLE state. - Calling resume() does not guarantee that the
target thread will become RUNNABLE other events
may have caused the thread to be NOT RUNNABLE or
even DEAD.
28The Thread API (cont.)
- Putting a Thread to Sleep
public static void sleep(long millisec) public
static void sleep(long millisec, int nanosec)
- Causes a thread to sleep for the specified number
of milliseconds ( the specified number of
nanoseconds).
public static void yield()
- Causes the currently executing thread object to
temporarily pause and allow other threads to
execute.
29The Thread API (cont.)
- Waiting for a Thread to End
public final void join() public final void
join(long millisec) public final void join(long
millisec, int nanosec)
- join() waits for this thread to die (joining the
thread). - join() methods with time parameters are used to
specify a timeout if the thread does not
terminate within the specified amount of time,
join() returns anyway.
30The Thread API (cont.)
- Understanding Daemon Threads
public final boolean isDaemon() public final
void setDaemon(boolean on)
- background threads providing service to other
threads. - When only daemon threads remain alive, the Java
VM process exits. - Garbage collection ? VM daemon thread, executing
only when there is nothing else for the system to
do. - setDaemon() method sets the daemon status of this
thread. - isDaemon() returns true if this thread is a
daemon otherwise it returns false.
31The Thread API (cont.)
- Miscellaneous Thread Methods
public int countStackFrames()
- Returns the number of active stack frames (method
activations) currently on this threads stack. - The thread must be suspended to use this method.
- suspend() ? deprecated ? countStackFrames() ?
deprecated.
public final ThreadGroup getThreadGroup()
- Returns the ThreadGroup to which this thread
belongs. - A thread is always member of a single ThreadGroup
class.
32The Thread API (cont.)
- Miscellaneous Thread Methods (cont.)
public final boolean isAlive()
- Returns true if this thread is RUNNABLE or NOT
RUNNABLE and false if this thread is NEW or DEAD.
public static Thread currentThread()
- Returns the Thread object for the current
sequence of execution.
public static int activeCount()
- Returns the number of threads in the currently
executing threads ThreadGroup class.
33The Thread API (cont.)
- Miscellaneous Thread Methods (cont.)
public static int enumerate(Thread tarray)
- Returns a list of all threads in the current
threads ThreadGroup class (including its
subgroups).
public static void dumpStack()
- Prints a method-by-method list of the stack trace
for the current thread to the System.err output
stream.
public String toString()
- Returns a string that describes this thread,
including the thread's name, priority, and thread
group.
34Exercise
- Implement a multithreaded server
- Server listens
- ? accept ? spawn a thread which processes the
clients request - Multiple clients can be served at the same time.
- Do it ! You will need it !
35Thread Groups
- Each Java thread belongs to one ThreadGroup
instance. - Used to assist with the organization of similar
groups of threads. - ThreadGroups can contain both threads and other
groups (tree-like structure). - The top thread group is named system.
36Thread Groups (cont.)
37The ThreadGroup API
public ThreadGroup(String name) public
ThreadGroup(ThreadGroup parent, String name)
- name is the name of the new ThreadGroup.
- parent is the parent group of the new
ThreadGroup. - The constructor that does not take the parent
parameter uses the group of the currently
executing thread as the parent of the new group. - Initially the new ThreadGroup object contains no
threads or other thread groups.
38The ThreadGroup API (cont.)
- API is similar to the Thread API.
- Methods that affect the whole group of threads.
- E.g. suspend, resume, stop, destroy all the
threads in the current group. - Methods that affect only the group attributes.
- E.g. setting priority for the current group.
- Consult the Java API for more details.
39Concurrency
- Performing multiple tasks ? managing concurrency!
- Requires the programmer to take special
precautions to ensure that Java objects are
accessed in a thread-safe manner. - Many concurrency-control solutions have been
proposed and implemented, e.g. critical sections,
semaphores, mutexes, monitors. - Java provides the programmer with the necessary
tools to manage concurrency ? implements a
variant of the monitor approach.
40Monitors
- Hoare (1974) describes a special-purpose object
called monitor which applies the principle of
mutual exclusion to groups of procedures. - Mutual exclusion one thread at a time.
- Hoares model
- Each group of procedures requiring mutual
exclusion is placed under the control of a single
monitor. - At run-time, the monitor allows only one thread
at a time to execute a procedure controlled by
the monitor. - If another thread tries to invoke a procedure
controlled by the monitor, that thread is
suspended until the first thread completes its
call.
41Monitors (cont.)
- Java monitors remain true to Hoares original
concept with a few minor variations. - Java monitors enforce mutually exclusive access
to synchronized methods. - Model
- Every Java object has an associated monitor.
- synchronized methods that are invoked on an
object use that objects monitor to limit
concurrent access to that object. - If no other thread is executing a synchronized
method on that object, the current thread is
allowed to enter (lock) the monitor, otherwise it
must wait until the other thread leaves the
monitor.
42Monitors (cont.)
- Java monitors are not like traditional critical
sections. - Declaring a method synchronized does not imply
that only one thread at a time can execute that
method, as it is the case with a critical
section. - Monitors imply that only one thread can invoke
that method (or any other synchronized method) on
a particular object at any given time. - Java monitors are associated with objects, not
with blocks of code. - Two threads can concurrently execute the same
synchronized method, provided that the method is
invoked on different objects.
43Monitors (cont.)
public class Counter private int count
0 public synchronized int incr() int n
count count n 1 return n
- Multiple threads access method incr().
- What happens ?
- What would happen if synchronized was omitted ?
44Deadlocks
- One of the worst situations that can happen in a
multithreaded environment. - Java programs are not immune to deadlocks ?
programmer must take care to avoid them. - Definition A situation that causes two or more
threads to hang (unable to proceed). - Simplest case two threads are each trying to
acquire a monitor that is already owned by the
other thread. - Each thread goes to sleep, waiting for the
desired monitor to become available but the
monitor never becomes available. - Java VM does not prevent or detect deadlocks.
- Algorithms available (see also Operating Systems).
45Synchronization
- Java monitors are more than locks.
- Monitors are also used to coordinate multiple
threads by using the wait() and notify() methods
available in every Java object. - Need for thread coordination
- threads are often interdependent one thread
can depend on another thread to complete an
operation or to service a request. - Threads are usually coordinated using a concept
known as a condition, or a condition variable.
46Synchronization (cont.)
- Condition logical statement that must hold
true in order for a thread to proceed.
while ( the_condition_I_am_waiting_for )
wait()
- Invoking wait() on an OBJECT pauses the current
thread and adds the thread to the condition
variable wait queue of the objects monitor. This
queue contains a list of all the threads that are
currently blocked inside wait() on that object. - The thread is not removed from the wait queue
until notify() is invoked on that OBJECT from a
different thread. - A call to notify() wakes a single waiting thread,
notifying the thread that a condition of the
object has changed.
47Synchronization (cont.)
void wait() void wait(long millisec) void
wait(long millisec, int nonosec)
- Time parameters specify a timeout, when you dont
want to wait indefinitely for an event.
void notify() void notifyAll()
- notifyAll() wakes up all threads that are waiting
on this object's monitor.
- ! these methods must be invoked from within a
synchronized method or a synchronized statement.
48A Thread Coordination Example
- Classic example the bounded buffer problem.
- Problem involves using a fixed-size memory buffer
to communicate between two processes or threads. - Solve the problem by coordinating the reader and
writer threads so that the following are true - When the writer thread (WT) attempts to write to
a full buffer, the WT is suspended until some
items are removed. - When the reader thread (RT) removes items from
the full buffer, the WT is notified of the
buffers changed condition and may continue
writing. - When the RT attempts to read from an empty
buffer, the RT is suspended until some items are
added to the buffer. - When the WT adds items to the empty buffer, the
RT is notified of the buffers changed condition
ad may continue reading.
49Coordination Example (cont.)
public class Producer implements Runnable
private Buffer buffer public Producer(Buffer
b) buffer b public void run() for
(int i 0 i lt 250 i) buffer.put((char)(
A(i 26))) // write to the buffer
50Coordination Example (cont.)
public class Consumer implements Runnable
private Buffer buffer public Consumer(Buffer
b) buffer b public void run() for
(int i 0 i lt 250 i) System.out.println(
buffer.get()) // read from the buffer
51Coordination Example (cont.)
public class Buffer private char buf //
buffer storage private int last // last
occupied position public Buffer(int sz) buf
new charsz last 0 public boolean
isFull() return (last buf.length) publ
ic boolean isEmpty() return (last 0)
52Coordination Example (cont.)
public synchronized void put(char c) while
(isFull()) // wait for room to put
stuff try wait() catch
(InterruptException e) buflast
c notify()
53Coordination Example (cont.)
public synchronized char get() while
(isEmpty()) // wait for stuff to read try
wait() catch (InterruptException e)
char c buf0 System.arraycopy(buf,
1, buf, 0, last) notify() return c //
end class Buffer
54Paradox
- When you first begin using wait() and notify(),
you may notice a contradiction ! - The wait() and notify() methods must be called
from synchronized methods, so if wait() is called
inside a synchronized method, how can a different
thread enter a synchronized method in order to
call notify () ??? Doesnt the waiting thread own
the objects monitor, preventing other threads
from entering the synchronized method ???
55Paradox (answer)
- wait() temporarily releases ownership of the
objects monitor before wait() can return,
however, it must reacquire ownership of the
monitor. By releasing the monitor, the wait()
method allows other threads to acquire ownership
of the monitor, which gives them the ability to
call notify().