MULTITHREADING
MULTITASKING
Multitasking refers to the simultaneously performance of multiple tasks and
processes by hardware, software or any computing appliance. It enables the performance of more
than one computer process at the same time with minimal lag in overall performance and without
affecting the operations of each task.
Multitasking is achieved by two ways multiprocessing and multithreading.
Multiprocessing
Multiprocessing is the capability of a computer to multitask, or execute more than one program or
process at the same time.
A process is heavyweight and requires the systems resources. For each process system allocates
different memory area. Thus the cost of communication between the process is high and switching
one process to another consumes time.
Thread
A thread is a smallest unit of process or subprocess of a process. It is lightweight and shares the
common memory and resources of the process. Hence communication between threads is simple
and switching one thread to another is also easy.
Multithreading is a technique used in operating systems to improve the performance and
responsiveness of computer systems by executing multiple threads . Multithreading allows multiple
threads (i.e., lightweight processes) to share the same resources of a single process, such as the CPU,
memory, and I/O devices.
Daemon thread: in Java is a low-priority thread that performs background operations such as
garbage collection, finalizer, Action Listeners, Signal dispatches, [Link] thread in Java is also a
service provider thread that helps the user thread. Its life is at the mercy of user threads; when all
user threads expire, JVM immediately terminates this thread.
Advantages of Thread
Responsiveness: If the process is divided into multiple threads, if one thread completes its
execution, then its output can be immediately returned.
Faster context switch: Context switch time between threads is lower compared to the process
context switch. Process context switching requires more overhead from the CPU.
Effective utilization of multiprocessor system: If we have multiple threads in a single process, then
we can schedule multiple threads on multiple processors. This will make process execution faster.
Resource sharing: Resources like code, data, and files can be shared among all threads within a
process. Note: Stacks and registers can’t be shared among the threads. Each thread has its own stack
and registers.
Communication: Communication between multiple threads is easier, as the threads share a
common address space. while in the process we have to follow some specific communication
techniques for communication between the two processes.
Enhanced throughput of the system: If a process is divided into multiple threads, and each thread
function is considered as one job, then the number of jobs completed per unit of time is increased,
thus increasing the throughput of the system.
Multithreading in java
Multithreading in Java is a process of executing multiple threads simultaneously. we use
multithreading than multiprocessing because threads use a shared memory area. They don't allocate
separate memory area so saves memory, and context-switching between the threads takes less time
than process. Java have Thread class to create threads
We have either extend Thread class or implement Runnable interface and give implementation to
run() method to create a thread
Java Multithreading is mostly used in games, animation, web development etc.
Note: only one thread is executed at a time in a single core processor
Life cycle of a thread in java
In Java, a thread always exists in any one of the following states. These states are:
1. New
2. Runnable
3. Running
4. Non Runnable(Blocked / Waiting/Timed Waiting)
5. Terminated
1. New
Whenever a new thread is created, it is always in the new state. For a thread in the new state, the
code has not been run yet and thus has not begun its execution. It is also referred to as a born
thread.
2. Runnable
A thread, that is ready to run is then moved to the runnable state. In the runnable state, the thread
may be running or may be ready to run at any given instant of time. It is the duty of the thread
scheduler to provide the thread time to run, i.e., moving the thread the running state.
A program implementing multithreading acquires a fixed slice of time to each individual thread. Each
and every thread runs for a short span of time and when that allocated time slice is over, the thread
voluntarily gives up the CPU to the other thread, so that the other threads can also run for their slice
of time. Whenever such a scenario occurs, all those threads that are willing to run, waiting for their
turn to run, lie in the runnable state. In the runnable state, there is a queue where the threads lie.
A thread enter this state when we call start method of Thread class.
3. Running
When the thread gets the CPU, it moves from the runnable to the running state. Generally, the most
common change in the state of a thread is from runnable to running and again back to runnable.
From here it can move to runnable ,non runnable or terminated state.
4. Non Runnable
Whenever a thread is inactive for a span of time (not permanently) then, either the thread is in the
blocked state or is in the waiting state. If there are a lot of threads in the waiting or blocked state,
then it is the duty of the thread scheduler to determine which thread to choose and which one to
reject, and the chosen thread is then given the opportunity to run.
From this state it can move to runnable ,running or terminated state.
Timed Waiting: thread lies in the waiting state for a specific span of time, and not forever. After the
time runs out, the thread wakes up and start its execution from when it has left earlier.
5. Terminated
A thread reaches this state When a thread has finished its job, then it exists or terminates normally
or Abnormal termination(It occurs when some unusual events such as an unhandled exception or
segmentation fault).
A terminated thread means the thread is no more in the system. In other words, the thread is dead,
and there is no way one can respawn the dead thread.
Thread class
Thread class provide constructors and methods to create and perform operations on a
[Link] class extends Object class and implements Runnable interface.
Fields : they are static and int
MAX_PRIORITY: The maximum priority that a thread can have.
MIN_PRIORITY: The minimum priority that a thread can have.
NORM_PRIORITY: The default priority that is assigned to a thread.
constructors
public Thread()àAllocates a new Thread object.
public Thread(Runnable target)àAllocates a new Thread [Link] - the object whose run
method is invoked when this thread is started. Pass a class object which implement Runnable
interface. This object is turn into thread object
public Thread(String name)àAllocates a new Thread object. name - the name of the new thread
public Thread(Runnable target, String name)àAllocates a new Thread object. parameters are same
as above.
Method:-
public static Thread currentThread() Returns a reference to the currently executing thread object.
public static void yield() A hint to the scheduler that the current thread is willing to yield
its current use of a processor.
public static void sleep(long millis) Causes the currently executing thread to sleep (temporarily cease
throws InterruptedException execution) for the specified number of milliseconds,
public static void sleep(long millis, Causes the currently executing thread to sleep (temporarily cease
int nanos) execution) for the specified number of milliseconds plus the
throws InterruptedException specified number of nanoseconds,
public void start() Causes this thread to begin execution; the Java Virtual Machine
calls the run method of this thread.
public void run() The method in runnable interface. This method’s code is executed
as thread. We should give implementation to this method
public final boolean isAlive() Tests if this thread is alive. A thread is alive if it has been started
and has not yet died.
public final void setPriority(int newPriority) Changes the priority of this thread.
public final int getPriority() Returns this thread's priority.
public final void setName(String name) Changes the name of this thread to be equal to the argument
name.
public final String getName() Returns this thread's name.
public final void join(long millis) Waits at most millis milliseconds for this thread to die. A timeout
throws InterruptedException of 0 means to wait forever.
public final void join(long millis, Waits at most millis milliseconds plus nanos nanoseconds for this
int nanos) thread to die.
throws InterruptedException
public final void join() Waits for this thread to die.
throws InterruptedException
public final void setDaemon(boolean on) Marks this thread as either a daemon thread or a user thread.
The Java Virtual Machine exits when the only threads running are
all daemon threads.
public final boolean isDaemon() Tests if this thread is a daemon thread.
public static boolean holdsLock(Object obj) Returns true if and only if the current thread holds the monitor
lock on the specified object.
public boolean isInterrupted() interrupts the thread.
public void interrupt() tests if the thread has been interrupted.
Creating thread in java
1. By extend the Thread class
We can create a thread by extending our thread class with Thread class and then provide a
implementation to the run() method. By doing this we cannot extend any other class. But it is the
easiest way.
Eg:
class Multi extends Thread{
public void run(){
[Link]("thread is running...");
}
public static void main(String args[]){
Multi t1=new Multi();
[Link]();
}
}
2. By implements the Runnable interface
This is the most common method of creating a thread. By implementing the runnable
interface and overriding the run() method we can create a thread. But we cannot get the
functionality of Thread class. So we convert this child of Runnable to a Thread object.
Eg:
class Multi3 implements Runnable{
public void run(){
[Link]("thread is running...");
}
public static void main(String args[]){
Multi3 m1=new Multi3();
Thread t1 =new Thread(m1); // Using the constructor Thread(Runnable r)
[Link]();
}
}
Synchronization in java
Synchronization in java is the capability to control the access of multiple threads to any shared
resource. In the Multithreading concept, multiple threads try to access the shared resources at a
time to produce inconsistent results. The synchronization is necessary for reliable communication
between threads. Synchronization helps in preventing thread interference and helps to prevent
concurrency problems. There are two types of Synchronization Process Synchronization and Thread
Synchronization.
A Mutex or Mutual Exclusive thread synchronization helps only one thread to access the shared
resources. It won’t allow the accessing of shared resources at a time. It can be achieved in the
following ways.
Synchronized Method
Synchronized block
Static Synchronization
Synchronization Mechanism developed by using the synchronized keyword in java language. It is
built on top of the locking mechanism, this locking mechanism is taken care of by Java Virtual
Machine (JVM). The synchronized keyword is only applicable for methods and blocks, it can’t apply
to classes and variables. Synchronized keyword in java creates a block of code is known as a critical
section. To enter into the critical section thread needs to obtain the corresponding object’s lock or
monitor.
Java Synchronized Method
If we use the Synchronized keywords in any method then that method is Synchronized Method. It is
used to lock an object for any shared resources. The object gets the lock when the synchronized
method is called. The lock won’t be released until the thread completes its function.
Syntax:
Acess_modifiers synchronized return_type method_name (Method_Parameters) {
// Code of the Method.
Eg:
class Power{
synchronized void printPower(int n){//method synchronized
int temp = 1;
for(int i=1;i<=5;i++){
[Link]([Link]().getName() + ":- " +n + "^"+ i + " value: " + n*temp);
temp = n*temp;
try{
[Link](500);
}catch(Exception e){[Link](e);}
}
}
}
class Thread1 extends Thread{
Power p;
Thread1(Power p){
this.p=p;
}
public void run(){
[Link](5);
}
}
class Thread2 extends Thread{
Power p;
Thread2(Power p){
this.p=p;
}
public void run(){
[Link](8);
}
}
public class Synchronization_Example2{
public static void main(String args[]){
Power obj = new Power();//only one object
Thread1 p1=new Thread1(obj);
Thread2 p2=new Thread2(obj);
[Link]();
[Link]();
}
}
Output:
Thread-0:- 5^1 value: 5
Thread-0:- 5^2 value: 25
Thread-0:- 5^3 value: 125
Thread-0:- 5^4 value: 625
Thread-0:- 5^5 value: 3125
Thread-1:- 8^1 value: 8
Thread-1: – 8^2 value: 64
Thread-1:- 8^3 value: 512
Thread-1:- 8^4 value: 4096
Thread-1:- 8^5 value: 32768
Synchronized Block
Suppose you don’t want to synchronize the entire method, you want to synchronize few lines of
code in the method, then a synchronized block helps to synchronize those few lines of code. It will
take the object as a parameter. It will work the same as Synchronized Method. In the case of
synchronized method lock accessed is on the method but in the case of synchronized block lock
accessed is on the object.
Syntax:
synchronized (object) {
//code of the block.
Eg:
class Power{
void printPower(int n){
synchronized(this){ //synchronized block
int temp = 1;
for(int i=1;i<=5;i++){
[Link]([Link]().getName() + ":- " +n + "^"+ i + " value: " + n*temp);
temp = n*temp;
try{
[Link](500);
}catch(Exception e){[Link](e);}
}
}
}
}
class Thread1 extends Thread{
Power p;
Thread1(Power p){
this.p=p;
}
public void run(){
[Link](5);
}
}
class Thread2 extends Thread{
Power p;
Thread2(Power p){
this.p=p;
}
public void run(){
[Link](8);
}
}
public class Synchronization_Example3{
public static void main(String args[]){
Power obj = new Power();//only one object
Thread1 p1=new Thread1(obj);
Thread2 p2=new Thread2(obj);
[Link]();
[Link]();
}
}
Output:
Thread-0:- 5^1 value: 5
Thread-0:- 5^2 value: 25
Thread-0:- 5^3 value: 125
Thread-0:- 5^4 value: 625
Thread-0:- 5^5 value: 3125
Thread-1:- 8^1 value: 8
Thread-1:- 8^2 value: 64
Thread-1:- 8^3 value: 512
Thread-1:- 8^4 value: 4096
Thread-1:- 8^5 value: 32768
Inter – Thread Communication
Inter – Thread communication or cooperation is a communication of two or more threads with each
other. It can be done by using the following methods. wait(), notify(), notifyAll().
There is a situation on the thread that keeps on checking some conditions repeatedly, once that
condition satisfies thread moves with the appropriate action. This situation is known as polling. This
is a wastage of CPU time, to reduce the wastage of CPU time due to polling, java uses Inter – Thread
Communication Mechanism.
wait () Method
It causes the current thread to place itself into the waiting stage until another thread invokes the
notify() method or notifyAll() method for this object.
Syntax: public final void wait()
notify () Method
This method wakes up a single thread called wait () on the same object. If there is more than one
thread that is waiting on this same object, then any one of them arbitrarily chosen to be awakened.
Here awakened thread will not able to proceed until the current thread release lock. If any threads
are trying to get the lock on this object then the awakened thread will also compete with them in
the usual manner.
Syntax: public final void notify()
notify All() Method
Rather than a single thread, it will wake up all the threads waiting on this object monitor. The
awakened thread will not able to proceed until the current thread releases the lock. Again, these
awakened threads need to compete with all other threads which are trying to get the lock on this
object.
Syntax: public final void notifyAll()
Deadlock in Java
Deadlock in Java is a part of multithreading. Deadlock can occur in a situation when a thread is
waiting for an object lock(monitor), that is acquired by another thread and second thread is waiting
for an object lock that is acquired by first thread. Since, both threads are waiting for each other to
release the lock, the condition is called deadlock.
Deadlocks cannot be completely resolved. But we can avoid them.
Avoid Nested Locks: We must avoid giving locks to multiple threads, this is the main reason for a
deadlock condition. It normally happens when you give locks to multiple threads.
Avoid Unnecessary Locks: The locks should be given to the important threads. Giving locks to the
unnecessary threads that cause the deadlock condition.
Using Thread Join: A deadlock usually happens when one thread is waiting for the other to finish. In
this case, we can use join with a maximum time that a thread will take.