Java Multithreading
By Abdo A.
1
Multithreading
The objectives of this chapter are:
To understand the purpose of multithreading
To describe Java's multithreading mechanism
To explain concurrency issues caused by multithreading
To outline synchronized access to shared resources
VM - virtual machine
OS - operating System
GUI - graphical user interface
2
Introduction
The unit of resource ownership is referred to as a process or task
The unit of dispatching is referred to as a thread or lightweight process
One or More Threads in a Process
In an OS that supports threads, scheduling and dispatching is done on a
thread basis
Most of the state information dealing with execution is maintained in
thread-level data structures
suspending a process involves suspending all threads of the process
termination of a process terminates all threads within the process
3
Threads and Processes
4
Threads vs. processes
Threads differ from traditional multitasking operating system processes
in that:
processes are typically independent, while threads exist as subsets of a
process
processes carry considerably more state information than threads,
whereas multiple threads within a process share process state as well
as memory and other resources
processes have separate address spaces, whereas threads share their
address space
processes interact only through system-provided inter-process
communication mechanisms
context switching between threads in the same process is typically
faster than context switching between processes.
Process creation is heavy-weight while thread creation is light-weight 5
Benefits of Threads
Less time to Threads enhance
terminate a Switching efficiency in
thread than a between two communication
Takes less process between programs
time to threads takes less
create a new time than
thread than switching
a process between
processes
6
What is Multithreading?
A multi-processing Operating System can run several
processes at the same time
Each process has its own address/memory space
The OS's scheduler decides when each process is executed
Only one process is actually executing at any given time.
However, the system appears to be running several
programs simultaneously
Separate processes to not have access to each other's
memory space
Many OSes have a shared memory system so that processes
can share memory space
Multithreading is similar to multi-processing.
In a multithreaded application, there are several points of
execution within the same memory space.
• Each point of execution is called a thread
• Threads share access to memory 7
Why use Multithreading?
In a single threaded application, one thread of execution must
do everything
If an application has several tasks to perform, those tasks will be
performed when the thread can get to them.
A single task which requires a lot of processing can make the
entire application appear to be "sluggish" or unresponsive.
In a multithreaded application, each task can be performed by a
separate thread
If one thread is executing a long process, it does not make the entire
application wait for it to finish.
If a multithreaded application is being executed on a system that has
multiple processors, the OS may execute separate threads
simultaneously on separate processors.
8
Multithreading vs. Single threading
Single threading: when the OS does not recognize the
concept of thread.
Multithreading: when the OS supports multiple threads of
execution within a single process.
MS-DOS supports a single user process and a single thread.
Older UNIXs supports multiple user processes but only
support one thread per process.
Solaris and Windows NT support multiple threads.
9
Multithreading vs. Single threading
10
multiple threads and multiprocessor
multiple threads within the same process can execute in parallel
on a multiprocessor
11
Why do we need threads?
Responsiveness – enhance parallel processing and utilize
the idle time of the CPU
Resource Sharing – threads share resources of process,
easier than shared memory or message passing
Economy – cheaper than process creation, thread switching
lower overhead than context switching
Scalability – process can take advantage of multiprocessor
architectures
Prioritize your work depending on priority
12
Example
Threads of execution
Each thread is a portion of a program that can execute
concurrently with other threads (multithreading)
Example: downloading a video clip
Instead of having to download the entire clip then play it:
Download a portion, play that portion, download the next
portion, play that portion... (streaming)
Ensure that it is done smoothly
13
What Kind of Applications Use
Multithreading?
Any kind of application which has distinct tasks which can be
performed independently
Any application with a GUI.
Threads dedicated to the GUI can delegate the processing of user requests to
other threads.
The GUI remains responsive to the user even when the user's requests are
being processed
Any application which requires asynchronous response
Network based applications are ideally suited to multithreading.
Data can arrive from the network at any time.
In a single threaded system, data is queued until the thread can read the data
In a multithreaded system, a thread can be dedicated to listening for data on
the network port. When data arrives, the thread reads it immediately and
processes it or delegates its processing to another thread 14
Example
Consider a simple web server
The web server listens for request and serves it
If the web server was not multithreaded, the requests
processing would be in a queue, thus increasing the
response time and also might hang the server if there
was a bad request.
By implementing in a multithreaded environment, the
web server can serve multiple request simultaneously
thus improving response time
15
How does it all work?
Each thread is given its own "context"
A thread's context includes virtual registers and its own calling stack
The "scheduler" decides which thread executes at any given time
The VM may use its own scheduler
Since many OSes now directly support multithreading, the
VM may use the system's scheduler for scheduling threads
The scheduler maintains a list of ready threads (the run queue)
and a list of threads waiting for input (the wait queue)
Each thread has a priority. The scheduler typically schedules
between the highest priority threads in the run queue
Note: the programmer cannot make assumptions about how
threads are going to be scheduled. Typically, threads will be
executed differently on different platforms. 16
Thread Support in Java
Few programming languages directly support threading
Although many have add-on thread support
Add on thread support is often quite cumbersome to use
The Java Virtual machine has its own runtime threads
Used for garbage collection
Threads are represented by a Thread class
A thread object maintains the state of the thread
It provides control methods such as interrupt, start, sleep, yield, wait
When an application executes, the main method is executed by a
single thread.
If the application requires more threads, the application must
create them.
17
Thread Support in Java
Applications are typically divided into processes during the
design phase, and a master process explicitly contains sub
processes and a single process may contain multiple threads
All threads within a process share the same state and same
memory space, and can communicate with each other
directly, because they share the same variables.
Threads are object in java language.
They can be created by using two different mechanisms.
By extending thread class or by implementing
Runnable interface.
18
Life cycle of a Thread (Thread States)
1. New If you create an instance of Thread
class but before the invocation of start() method.
2. Runnable After invocation of start() method,
but the thread scheduler has not selected it to be
the running thread.
3. Running if the thread scheduler has selected
it. System assigns processor to thread (thread
begins executing) When run completes or
terminates, enters dead state
4. Non-Runnable Still alive, but is currently
not eligible to run.
i. Waiting − Sometimes, a thread transitions to
the waiting state while the thread waits for
another thread to perform a task.
ii. Timed Waiting/sleeping, suspend()
an I/O operation
5. Terminated
dead state when its run() method exits.
19
Life cycle of a Thread (Thread States)
20
Other Thread States
Blocked state
Entered from running state
Blocked thread cannot use processor, even if available
Common reason for blocked state - waiting on I/O request
Sleeping state
Entered when sleep method called
Cannot use processor
Enters ready state after sleep time expires
Waiting state
Entered when wait called in an object thread is accessing
One waiting thread becomes ready when object calls notify
notifyAll - all waiting threads become ready
21
Thread Methods
static void sleep( long milliseconds )
Thread sleeps (does not contend for processor) for number of
milliseconds
Why might we want a program to invoke sleep?
Can give lower priority threads a chance to run
void interrupt() - interrupts a thread
boolean isInterrupted()
Determines if a thread is interrupted
boolean isAlive()
Returns true if start called and thread not dead (run has not
completed)
getPriority() - returns this thread's priority
setPriority() – sets this threads priority
Etc. 22
A. Extending the Thread Class
The steps for creating a thread are:
1. Create a class by extending the Thread class and
override the run() method:
public class MyThread extends Thread {
public void run(){
System.out.println("this is the thread to be executed");
}
}
2. Create a thread object:
MyThread thr1 = new MyThread();
3. Start Execution of created thread:
thr1.start(); 23
Implementing the Runnable Interface
1. Create a class that implements the interface Runnable and override
run() method:
2. Create an Object of the class which implement the Runnable interface
3. Creating a generic Thread Object and pass the object created in step 2 as
a parameter
4. Start Execution: call the start method using the generic thread object
public class MyThread implements Runnable { //step 1
public void run(){
System.out.println("this is the thread to be executed"); } }
class ThreadEx1 {
public static void main(String [] args ) {
MyThread th=new MyThread (); //step-2
Thread t = new Thread(th); //step -3
t.start(); //step -4 }} 24
Thread Class vs Runnable Interface
It is a little confusing why there are two ways of doing the
same thing in the threading API. It is important to understand
the implication of using these two different approaches.
By extending the thread class, the derived class itself is a
gains full control over the thread life cycle.
Runnable interface does not give developers any control over the
thread itself, as it simply defines the unit of work that will
be executed in a thread.
Another important point is that when extending the Thread
class, the derived class cannot extend any other base.
By implementing the Runnable interface, the class can still
extend other base classes if necessary. 25
Thread Class vs Runnable Interface
To summarize, if the program needs a full control over the
thread life cycle, extending the Thread class is a good
choice, and
If the program needs more flexibility of extending other
base classes, implementing the Runnable interface would
be preferable. If none of these is present, either of them is
fine to use
26
Properly Terminating Threads
In Java 1.1, the Thread class had a stop() method
One thread could terminate another by invoking its stop()
method.
However, using stop() could lead to deadlocks
The stop() method is now deprecated. DO NOT use the
stop method to terminate a thread
The correct way to stop a thread is to have the run method
terminate
Add a boolean variable which indicates whether the
thread should continue or not
Provide a set method for that variable which can be
invoked by another thread
27
Creating Multiple Threads
The previous example illustrates a Runnable class which creates
its own thread when the start method is invoked.
If one wished to create multiple threads, one could simple create
multiple instances of the Runnable class and send each object a
start message
Each instance would create its own thread object
Is the a maximum number of threads which can be created?
There is no defined maximum in Java.
If the VM is delegating threads to the OS, then this is platform
dependent.
A good rule of thumb for maximum thread count is to allow 2Mb
of ram for each thread
Although threads share the same memory space, this can be a
reasonable estimate of how many threads your machine can handle. 28
Thread Priorities
Every thread is assigned a priority (between 1 and 10)
The default is 5, and the higher the number, the higher the priority
Can be set with setPriority(int aPriority)
The standard mode of operation is that the scheduler executes threads
with higher priorities first.
This simple scheduling algorithm can cause problems. Specifically, one
high priority thread can become a "CPU hog".
A thread using vast amounts of CPU can share CPU time with other
threads by invoking the yield() method on itself.
Most OSes do not employ a scheduling algorithm as simple as this one
Most modern OSes have thread aging
o The more CPU a thread receives, the lower its priority becomes
o The more a thread waits for the CPU, the higher its priority becomes
o Because of thread aging, the effect of setting a thread's priority is
dependent on the platform 29
Yield() and Sleep()
Sometimes a thread can determine that it has nothing to do
Sometimes the system can determine this. ie. waiting for I/O
When a thread has nothing to do, it should not use CPU
This is called a busy-wait.
Threads in busy-wait are busy using up the CPU doing nothing.
Often, threads in busy-wait are continually checking a flag to see if there is anything to do.
It is worthwhile to run a CPU monitor program on your desktop
You can see that a thread is in busy-wait when the CPU monitor goes up
(usually to 100%), but the application doesn't seem to be doing anything.
Threads in busy-wait should be moved from the Run queue to the Wait queue
so that they do not monopolize the CPU
Use yield() or sleep(time)
Yield simply tells the scheduler to schedule another thread
Sleep guarantees that this thread will remain in the wait queue for the specified number of
milliseconds.
30
Concurrent Access to Data
Those familiar with databases will understand that concurrent access to
data can lead to data integrity problems
Specifically, if two sources attempt to update the same data at the
same time, the result of the data can be undefined.
The outcome is determined by how the scheduler schedules the two
sources. Since the schedulers activities cannot be predicted, the
outcome cannot be predicted
Databases deal with this mechanism through "locking"
If a source is going to update a table or record, it can lock the table or
record until such time that the data has been successfully updated.
While locked, all access is blocked except to the source which holds
the lock.
Java has the equivalent mechanism. It is called synchronization
Java has a keyword called synchronized
31
Synchronization
In Java, every object has a lock
To obtain the lock, you must synchronize with the object
The simplest way to use synchronization is by declaring one or
more methods to be synchronized
When a synchronized method is invoked, the calling thread attempts
to obtain the lock on the object.
if it cannot obtain the lock, the thread goes to sleep until the lock
becomes available
Once the lock is obtained, no other thread can obtain the lock until it
is released. i.e, the synchronized method terminates
When a thread is within a synchronized method, it knows that no
other synchronized method can be invoked by any other thread
Therefore, it is within synchronized methods that critical data is
updated 32
Providing Thread Safe Access to Data
If an object contains data which may be updated from
multiple thread sources, the object should be implemented
in a thread-safe manner
All access to critical data should only be provided through
synchronized methods (or synchronized blocks).
In this way, we are guaranteed that the data will be updated by only
one thread at a time.
public class SavingsAccount {
private float balance;
public synchronized void withdraw(float anAmount){
if ((anAmount>0.0) && (anAmount<=balance))
balance = balance - anAmount;
}
public synchronized void deposit(float anAmount) {
if (anAmount>0.0)
balance = balance + anAmount;
} 33
Thread Safety Performance Issues
However, there is an overhead associated with synchronization
Many threads may be waiting to gain access to one of the object's
synchronized methods
The object remains locked as long as a thread is within a synchronized
method.
Ideally, the method should be kept as short as possible.
Another solution is to provide synchronization on a block of
code instead of the entire method
In this case, the object's lock is only held for the time that the thread is
within the block.
The intent is that we only lock the region of code which requires access to
the critical data. Any other code within the method can occur without the lock.
In high load situations where multiple threads are attempting to access
critical data, this is by far a much better implementation.
34
Block Synchronization
public class SavingsAccount {
private float balance;
public void withdraw(float anAmount) {
if (anAmount<0.0)
throw new IllegalArgumentException("Withdraw amount
negative");
synchronized(this) {
if (anAmount<=balance)
balance = balance - anAmount;
}
}
public void deposit(float anAmount) {
if (anAmount<0.0)
throw new IllegalArgumentException("Deposit amount
negative");
synchronized(this)
{
balance = balance + anAmount;
}} 35
The end
Thank you!
36