Unit 5 Multithreading
Unit 5 Multithreading
Unit 5 Multithreading
Multitasking
Multitasking is a process of executing multiple tasks simultaneously. We use
multitasking to utilize the CPU. Multitasking can be achieved in two ways:
o Process-based Multitasking (Multiprocessing)
o Thread-based Multitasking (Multithreading)
1) Process-based Multitasking (Multiprocessing)
o Each process has an address in memory. In other words, each process
allocates a separate memory area.
o A process is heavyweight.
o Cost of communication between the process is high.
o Switching from one process to another requires some time for saving and
loading registers, memory maps, updating lists, etc.
2) Thread-based Multitasking (Multithreading)
o Threads share the same address space.
o A thread is lightweight.
o Cost of communication between the thread is low.
o
Multithreading in Java
Multithreading in Java is a process of executing multiple threads
simultaneously.
Thread:-
1) Thread is nothing but separate path of sequential execution.
2) The independent execution technical name is called thread.
3) Whenever different parts of the program executed simultaneously that each
and every part is called thread.
4) The thread is light weight process because whenever we are creating thread it
is not occupying the separate memory it uses the same memory. Whenever the
memory is shared means it is not consuming more memory.
5) Executing more than one thread a time is called multithreading.
Life cycle of a Thread (Thread States)
In Java, a thread always exists in any one of the following states. These states are:
1. New State
2. Runnable State
3. Blocked State
4. Waiting State
5. Timed Waiting State
6. Terminated State
1
Unit 5 Multithreading
Thread States
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.
Active: When a thread invokes the start() method, it moves from the new state to
the active state. The active state contains two states within it: one is runnable,
and the other is running.
o 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.
o 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.
Blocked or Waiting: 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.
For example, a thread (let's say its name is A) may want to print some data from
the printer.
2
Unit 5 Multithreading
However, at the same time, the other thread (let's say its name is B) is using the
printer to print some data. Therefore, thread A has to wait for thread B to use the
printer. Thus, thread A is in the blocked state. A thread in the blocked state is
unable to perform any execution and thus never consume any cycle of the Central
Processing Unit (CPU). Hence, we can say that thread A remains idle until the
thread scheduler reactivates thread A, which is in the waiting or blocked
state.When the main thread invokes the join() method then, it is said that the
main thread is in the waiting state. The main thread then waits for the child
threads to complete their tasks. When the child threads complete their job, a
notification is sent to the main thread, which again moves the thread from waiting
to the active 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.
Timed Waiting: Sometimes, waiting for leads to starvation. For example, a
thread (its name is A) has entered the critical section of a code and is not willing
to leave that critical section. In such a scenario, another thread (its name is B) has
to wait forever, which leads to starvation. To avoid such scenario, a timed waiting
state is given to thread B. Thus, thread lies in the waiting state for a specific span
of time, and not forever. A real example of timed waiting is when we invoke the
sleep() method on a specific thread. The sleep() method puts the thread in the
timed wait state. After the time runs out, the thread wakes up and start its
execution from when it has left earlier.
Terminated: A thread reaches the termination state because of the following
reasons:
o When a thread has finished its job, then it exists or terminates normally.
o 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 (active after kill) the dead
thread.
The following diagram shows the different states involved in the life cycle of a
thread.
Java Threads | How to create a thread in Java
There are two ways to create a thread:
1. By extending Thread class
2. By implementing Runnable interface.
Thread class:
Thread class provide constructors and methods to create and perform operations
on a thread.Thread class extends Object class and implements Runnable
interface.
Commonly used Constructors of Thread class:
o Thread()
3
Unit 5 Multithreading
o Thread(String name)
o Thread(Runnable r)
o Thread(Runnable r,String name)
Thread()
The default Thread() constructor is used to create a new Thread class.
class TestThread extends Thread
{
public static void main(String args[])
{
Thread t1= new Thread();
t1.start();
Thread t2= new Thread();
System.out.println("Thread t1 in executed " +t1.getName());
System.out.println("Thread t2 in executed " +t2.getName());
}
}
Thread (String str)
A thread object is created and a name is provided to the same.
class TestThread extends Thread
{
public static void main(String args[])
{
Thread t1= new Thread(" THREAD ONE");
t1.start();
System.out.println("Thread t1 in executed " +t1.getName());
}
}
Thread (Runnable r)
In this constructor type, Runnable reference is passed and a new Thread object
is created
class Test implements Runnable
{
public void run()
{
System.out.println("Call from run inside test class");
}
}
class TestThread
{
public static void main(String args[])
{
Test t= new Test();
4
Unit 5 Multithreading
5
Unit 5 Multithreading
}
run() Method of the Runnable Interface
The Runnable interface comes with a single method, run(). The run() method
will be executed by Java when a thread is started with the class instance that
implements the Runnable interface. The run() method is treated as the starting
point of the class being executed by a thread.
Steps to Create a New Thread Using Runnable Interface in Java
We can create a new thread using the Runnable interface by following the
steps below:
Create a class that implements the Runnable interface.
Override the run() method of the Runnable interface in the class.
Create a Thread object in the main class by passing the class object that
implemented the Runnable interface.
Call the start() method of the Thread object.
Thread Sleep()
Thread.sleep() interacts with the thread scheduler to put the current thread in a
wait state for a specified period of time. Once the wait time is over, the thread
state is changed to a runnable state and waits for the CPU for further execution.
The actual time that the current thread sleeps depends on the thread scheduler
that is part of the operating system.
Java Thread.sleep important points
1. It always pauses the current thread execution.
2. The actual time the thread sleeps before waking up and starting execution
depends on system timers and schedulers. For a quiet system, the actual time
for sleep is near to the specified sleep time, but for a busy system, it will be a
little bit longer.
3. Thread.sleep() doesn’t lose any monitors or lock the current thread it has
acquired.
4. Any other thread can interrupt the current thread in sleep, and in such
cases InterruptedException is thrown.
import java.io.*;
import java.lang.*;
class TestThread
{
public static void main(String args[])
{
try {
for (int i = 0; i < 5; i++)
{
6
Unit 5 Multithreading
Thread.sleep(1000);
System.out.println(i);
}
}
catch(Exception e)
{
System.out.println(e);
}
}
}
Program2
import java.io.*;
import java.lang.*;
class Test extends Thread
{
public void run()
{
try {
for (int i = 0; i < 5; i++)
{
Thread.sleep(1000);
System.out.println(i);
}
}
catch(Exception e)
{
System.out.println(e);
}
}
}
class TestThread
{
public static void main(String args[])
{
Test t= new Test();
t.start();
}
}
7
Unit 5 Multithreading
import java.io.*;
import java.lang.*;
class Test extends Thread
{
public void run()
{
try {
for (int i = 0; i < 5; i++)
{
Thread.sleep(1000);
System.out.println(i);
}
}
catch(InterruptedException e)
{
System.out.println(e);
}
}
}
class TestThread
{
public static void main(String args[])
{
Test t= new Test();
t.start();
try
{
t.interrupt();
}
catch(Exception e)
{
System.out.println("Exception is handled "+e);
}
8
Unit 5 Multithreading
}
}
Thread join() method
The join() method of thread class waits for a thread to die. It is used when you
want one thread to wait for completion of another. This process is like a relay race
where the second runner waits until the first runner comes and hand over the
flag to him.
Join method allows one thread to wait for the completion of another
thread.
t.join(); ---> here t is a Thread Object whose thread is currently running.
o Join() is used to stop the execution of the thread until completion of
some other Thread.
9
Unit 5 Multithreading
}
}
catch(Exception e)
{
e.printStackTrace();
System.out.println(e);
}
}
}
class TestThread extends Thread
{
public static void main(String args[])
{
MyThread t= new MyThread();
Thread t1= new Thread(t,"Thread T1");
Thread t2= new Thread(t,"Thread T2");
Thread t3= new Thread(t,"Thread T3");
t1.start();
try
{
t1.join();
}
10
Unit 5 Multithreading
catch(Exception e)
{
System.out.println("Exception is handled "+e);
}
t3.start();
t2.start();
}
}
Thread Priorities:-
Every Thread in java has some property. It may be default priority
provided be the JVM or customized priority provided by the programmer.
The valid range of thread priorities is 1 – 10. Where one is lowest priority
and 10 is highest priority.
The default priority of main thread is 5. The priority of child thread is
inherited from the parent.
Thread defines the following constants to represent some standard
priorities.
Thread Scheduler will use priorities while allocating processor the thread
which is having highest priority will get chance first and the thread which
is having low priority.
If two threads having the same priority then we can’t expect exact
execution order it depends upon Thread Scheduler.
The thread which is having low priority has to wait until completion of
high priority threads.
Three constant values for the thread priority.
a. MIN_PRIORITY = 1
b. NORM_PRIORITY = 5
c. MAX_PRIORITY = 10
Thread class defines the following methods to get and set priority of a Thread.
Public final int getPriority()
Public final void setPriority(int priority)
Here ‘priority’ indicates a number which is in the allowed range of 1 – 10.
Otherwise we will get
Runtime exception saying “IllegalArgumentException”.
Thread priority decide when to switch from one running thread to another
this process is called context switching.
{
System.out.println("current Thread name =
"+Thread.currentThread().getName());
System.out.println("current Thread priority =
"+Thread.currentThread().getPriority());
}
}
class ThreadDemo
{
public static void main(String[] args)//main thread started
{
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.MAX_PRIORITY);
System.out.println("current Thread priority =
"+Thread.currentThread().getPriority());
t1.start();
t2.start();
}
}
Synchronization in Java
Synchronization in Java is the capability to control the access of multiple threads
to any shared resource.
Java Synchronization is better option where we want to allow only one thread to
access the shared resource.The synchronization is mainly used to
1. To prevent thread interference.
2. To prevent consistency problem.
Types of Synchronization
There are two types of synchronization
1. Process Synchronization
2. Thread Synchronization
Thread Synchronization
There are two types of thread synchronization mutual exclusive and inter-thread
communication.
1. Mutual Exclusive
1. Synchronized method.
2. Synchronized block.
3. Static synchronization.
2. Cooperation (Inter-thread communication in java)
12
Unit 5 Multithreading
Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another while
sharing data. It can be achieved by using the following three ways:
1. By Using Synchronized Method
2. By Using Synchronized Block
3. By Using Static Synchronization
Inter-thread Communication in Java
Inter-thread communication or Co-operation is all about allowing
synchronized threads to communicate with each other.
Cooperation (Inter-thread communication) is a mechanism in which a thread is
paused running in its critical section and another thread is allowed to enter (or
lock) in the same critical section to be executed.It is implemented by following
methods of Object class:
o wait()
o notify()
o notifyAll()
Synchronized :-
Synchronized modifier is the modifier applicable for methods but not for
classes and variables.
If a method or a block declared as synchronized then at a time only one
Thread is allowed to operate on the given object.
The main advantage of synchronized modifier is we can resolve data
inconsistency problems.
But the main disadvantage of synchronized modifier is it increases the
waiting time of theThread and effects performance of the system .Hence if
there is no specific requirement it is never recommended to use.
The main purpose of this modifier is to reduce the data inconsistence
problems.
Non-synchronized methods
void m1()
{
non-synchronized method any number of threads can access
}
1) In the above case multiple threads are accessing the same methods hence we
are getting data inconsistency problems. These methods are not thread safe
methods.
13
Unit 5 Multithreading
2) But in this case multiple threads are executing so the performance of the
application will be increased.
Synchronized methods
synchronized void m2()
{
}
Only one thread allowed to access
Thread 1 Thread 2 Thread 3---------Thread N
1) In the above case only one thread is allow to operate on particular method so
the data inconsistency problems will be reduced.
2) Only one thread is allowed to access so the performance of the application
will be reduced.
3) If we are using above approach there is no multithreading concept.
Hence it is not recommended to use the synchronized modifier in the
multithreading programming.
Program using Static synchronization method
Example :-
import java.io.*;
import java.lang.*;
class TThread
{
public static synchronized void demo(String s)
{
try
{
System.out.println("Inside " +s);
for (int i = 0; i < 5; i++)
{
Thread.sleep(1000);
System.out.println("Thread " +Thread.currentThread().getName()+" is
Started " +i);
}
}
catch(Exception e)
{
e.printStackTrace();
System.out.println(e);
}
14
Unit 5 Multithreading
}
}
class MyThread1 extends Thread
{
public void run()
{
TThread.demo("Thread T1");
}
}
class MyThread2 extends Thread
{
public void run()
{
TThread.demo("Thread T2");
}
}
class MyThread3 extends Thread
{
public void run()
{
TThread.demo("Thread T3");
}
}
class TestThread extends Thread
{
public static void main(String args[])
{
MyThread1 t1= new MyThread1();
MyThread2 t2= new MyThread2();
MyThread3 t3= new MyThread3();
t1.start();
t2.start();
t3.start();
}
}
Program using synchronization method
class Table
{
synchronized void printTable(int n)
{
//synchronized method
for(int i=1;i<=10;i++)
{
System.out.println(n*i);
15
Unit 5 Multithreading
try
{
Thread.sleep(400);
}
catch(Exception e){System.out.println(e);}
}
}
}
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run()
{
t.printTable(100);
}
}
class Account
{
wait();
}
catch (Exception e)
{
}
}
totalBalance -= withdrawAmt;
System.out.println(Thread.currentThread().getName() + " :
withdrawlcompleted. Remaining Balance = " + totalBalance);
}
synchronized void depositMoney(int depositAmt)
{
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " : depositing " + depositAmt);
totalBalance += depositAmt;
System.out.println(threadName + " : deposit of money done. Total balance = " +
totalBalance);
System.out.println(threadName + " : You can withdraw now.");
notifyAll();
}
}
class ThreadComm
{
public static void main(String args[]) throws InterruptedException
{
Account acct = new Account();
Thread t1 = new Thread()
{
public void run()
{
acct.withdrawMoney(10000);
}
};
t1.start();
Thread.sleep(10000);
Thread.sleep(10000);
Thread t3 = new Thread()
{
public void run()
{
acct.depositMoney(5000);
}
};
t3.start();
}
}
19