|
Short notes on Multithreading [ Tutorial ] |
|
|
Written by Veena Devi
|
This is a short tutorial on Multithreading
What are Threads?
-
A thread is a single sequential flow of control within a program
-
Facility to allow multiple activities within a single process
-
Referred as lightweight process
-
Each thread has its own program counter, stack and local variables
-
Threads share memory, heap area, files
Why use Threads?
-
To perform asynchronous or background processing
-
Increases the responsiveness of GUI applications
-
Better utilization of system resources
-
Simplify program logic when there are multiple independent entities
Creating the Thread
Two ways:
-
Extending the Thread class
- Implementing the Runnable interface
The Thread class
-
Override the run() method
-
Create an object of the sub class and call the start method to execute the Thread
The Runnable Interface
-
Useful when the class is already extending another class and needs to implement mutithreading
-
Need to implement the run() method
-
Create a thread object (the worker) and give it a Runnable object (the job)
– public Thread(Runnable target);
-
Start the thread by calling the start() method

Thread scheduling
-
There are 2 techniques for thread scheduling
– Pre-emptive and time-sliced
-
In preemptive scheduling, the thread with a higher priority preempts threads with lower priority and grabs the CPU
-
In time-sliced or round robin scheduling, each thread will get some time of the CPU
- Java runtime system’s thread scheduling algorithm is preemptive but it depends on the implementation
-
Solaris is preemptive, Macintosh and Windows are time sliced
-
In theory, a thread with high priority should get more CPU time, but practically it may depend on the platform
Thread Priorities
-
Thread priority can be used by the scheduler to decide which thread is to be run
-
The priority of a Thread can be set using the method setPriority()
– t.setPriority(7);
-
The method getPriority() will return the priority of a Thread
– t.getPriority()
-
The priority can vary from 1 to 10 or Thread.MIN_PRIORITY to
Thread.MAX_PRIORITY
-
Normally a Thread will have the priority 5 or Thread.NORM_PRIORITY
Ensuring time-slicing
-
The programmer should write code to ensure that time-slicing occurs even when the application is running in a preemptive environment
-
The static method sleep of the Thread class will make a thread sleep for specified number of milliseconds
Thread.sleep(1000);
-
A sleeping thread can be interrupted by another thread using the method interrupt()
-
When interrupted, sleep method will throw an InterruptedException
- The yield method of the class Thread will give a chance to other threads to run
– t.yield();
-
The yield() method ensures that the thread behaves like a polite thread and not a selfish thread
isAlive() and join() methods
The state of a thread can be queried using the isAlive() method
– Returns true if the thread has been started but not completed its task
– A thread can wait for another thread to finish by using the join() method
Thread synchronization
-
In a multithreaded environment 2 or more threads may access a shared resource
-
There should be some means to ensure that the shared resource is accessed by only one thread at a time. This is termed as synchronization
-
Every object has a mutually exclusive lock called monitor
-
Only one thread can get the monitor of an object at a time
- Synchronization can be ensured by using the keyword synchronized
-
A method or block of code can be made synchronized
Example
public class Account{
int bankBalance;
public synchronized void creditAccount (int amount) {
bankBalance+= amount;
}
}
Inter-thread communication
-
If a thread must wait for the state of an object to change while executing a synchronized method, it may call wait()
– void wait()
– void wait (long timeout)
-
The thread calling wait will release the lock on that particular object
-
The thread will wait till it is notified by another thread owning the lock on the same object
– void notify()
– void notifyAll()
-
If there are multiple threads waiting on the same object, the notify() method will notify one among them
-
The thread that would be notified cannot be predicted
-
It is safer to call notifyAll(), since it will notify all waiting threads
-
Code for synchronization should be written carefully else may lead to a deadlock situation
Example
public class Account {
int bankBalance;
public synchronized void debitAccount (int amount) {
while((bankBalance - amount)<0) wait();
bankBalance -= amount;
…
}
public synchronized void creditAccount (int amount) {
bankBalance += amount;
notify();
…
}
}
Thread Groups
-
Represents a set of threads
-
Can also contain other thread groups, creating a hierarchy of thread groups
-
Provides a single-point control on the threads belonging to the thread group
-
Creation time association is for the life time of the thread
– ThreadGroup threadGroup = new ThreadGroup("MyGroup");
-
Some of the important methods of ThreadGroup are
– activeCount(), destroy(), setMaxPriority(), setDaemon()
Daemon Thread
-
Daemon Thread is a thread that will run in the background, serving other threads
-
So, a program can stop, if all non-daemon threads have finished execution
-
A thread can be made a daemon by calling the method setDaemon(true) before calling its start() method
-
Can query thread status using the method isDaemon()
|