Multi-threading
Multitasking
Thread concept
Thread life cycle
Thread class
Runnable interface
Synchronization
Thread class methods.
Multitasking
Multitasking is a process of executing multiple tasks simultaneously.
We use multitasking to utilize the CPU. Multitasking can be achieved
in two ways:
Process-based Multitasking (Multiprocessing)
Thread-based Multitasking (Multithreading)
1) Process-based Multitasking (Multiprocessing)
Each process has an address in memory. In other words, each
process allocates a separate memory area.A process is
heavyweight.Cost of communication between the process is
high.Switching from one process to another requires some time
for saving and loading registers, memory maps, updating lists, etc.
2) Thread-based Multitasking (Multithreading)
Threads share the same address space.A thread is lightweight.Cost
of communication between the thread is low.
What is Thread in java
A thread is a lightweight subprocess,
the smallest unit of processing. It is a
separate path of execution.
Threads are independent. If there
occurs exception in one thread, it
doesn't affect other threads. It uses a
shared memory area.
As shown in the figure, a thread is
executed inside the process. There is
context-switching between the
threads. There can be multiple
processes inside the OS, and one
process can have multiple threads.
Multithreading in Java
Multithreading in Java is a process of executing multiple threads
simultaneously.
A thread is a lightweight sub-process, the smallest unit of processing.
Multiprocessing and multithreading, both are used to achieve multitasking.
However, 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 Multithreading is mostly used in games, animation, etc.
Advantages of Java Multithreading
1) It doesn't block the user because threads are independent and you can
perform multiple operations at the same time.
2) You can perform many operations together, so it saves time.
3) Threads are independent, so it doesn't affect other threads if an
exception occurs in a single thread.
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
2.Active
3.Blocked / Waiting
4.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.
2. 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.
1.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.
2.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.
1.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.
2.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.
1.Terminated: A thread reaches the termination state because of the
following reasons:
When a thread has finished its job, then it exists or terminates normally.
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 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:
By extending Thread class
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:
Thread()
Thread(String name)
Thread(Runnable r)
Thread(Runnable r,String name)
Commonly used methods of Thread class:
public void run(): is used to perform action for a thread.
public void start(): starts the execution of the thread.JVM calls the
run() method on the thread.
public void suspend(): is used to suspend the thread(depricated).
public void resume(): is used to resume the suspended
thread(depricated).
public void stop(): is used to stop the thread(depricated).
public int getId(): returns the id of the thread.
public String getName(): returns the name of the thread.
public void setName(String name): changes the name of the thread.
public void sleep(long miliseconds): Causes the currently executing
thread to sleep (temporarily cease execution) for the specified number
of milliseconds.
Runnable Interface:
The Runnable interface should be implemented by any class whose
instances are intended to be executed by a thread. Runnable
interface have only one method named run().
public void run(): is used to perform action for a thread.
Starting a thread:
The start() method of Thread class is used to start a newly created
thread. It performs the following tasks:
A new thread starts(with new callstack).
The thread moves from New state to the Runnable state.
When the thread gets a chance to execute, its target run() method will
run.
1) Java Thread Example by extending Thread class
class Multi extends Thread{
public void run(){ Output:
System.out.println("thread is
running..."); thread is running...
}
public static void main(String args[]){
Multi t1=new Multi();
t1.start();
}
}
2) Java Thread Example by implementing Runnable
interface Output:
class Multi3 implements Runnable{
public void run(){ thread is running...
System.out.println("thread is
running..."); Note:If you are not extending the
} Thread class, your class object
would not be treated as a thread
public static void main(String args[]){ object. So you need to explicitly
Multi3 m1=new Multi3(); create the Thread class object. We
Thread t1 =new Thread(m1); // Using
the constructor Thread(Runnable r) are passing the object of your class
t1.start(); that implements Runnable so that
} your class run() method may
} execute.
3) Using the Thread Class: Thread(String Name)
We can directly use the Thread class to spawn new threads using the
constructors defined above. Output:
public class MyThread1
{
// Main method My first thread
public static void main(String argvs[])
{
// creating an object of the Thread class using the constructor Thread(String
name)
Thread t= new Thread("My first thread");
// the start() method moves the thread to the active state
t.start();
// getting the thread name by invoking the getName() method
String str = t.getName();
System.out.println(str);
} }
4) Using the Thread Class: Thread(Runnable r, String
// creating an object of the class Thread using
name) Thread(Runnable r, String name)
Thread th1 = new Thread(r1, "My new thread");
public class MyThread2 implements Runnable
{
// the start() method moves the thread to the active
public void run() state
{ th1.start();
System.out.println("Now the thread is running ...");
} // getting the thread name by invoking the getName()
method
// main method String str = th1.getName();
public static void main(String argvs[]) System.out.println(str);
{ } }
// creating an object of the class MyThread2 Output:
Runnable r1 = new MyThread2();
My new thread
Now the thread is running ...
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 :
To prevent thread interference.
To prevent consistency problem.
Types of Synchronization:
There are two types of synchronization:
Process Synchronization
Thread Synchronization
Thread Synchronization
There are two types of thread synchronization mutual exclusive and
inter-thread communication.
1.Mutual Exclusive
Synchronized method.
Synchronized block.
Static synchronization.
1. Cooperation (Inter-thread communication in java)
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:
By Using Synchronized Method
By Using Synchronized Block
By Using Static Synchronization
Understanding the problem without Synchronization
class Table{ class
class MyThread1 class TestSynchronization1
void printTable(int n) extends Thread{ MyThread2 {
{//method not
synchronized Table t; extends public static void
MyThread1(Tabl Thread{ main(String args[]){
for(int i=1;i<=5;i++){ Table obj = new
e t){ Table t; Table();//only one
System.out.println(n*i); this.t=t; MyThread2(Tab object
try{
Thread.sleep(400); } le t){ MyThread1 t1=new
MyThread1(obj);
}catch(Exception e) public void run(){ this.t=t; MyThread2 t2=new
{System.out.println(e);} t.printTable(5); } MyThread2(obj);
} } public void t1.start();
run(){ t2.start();
} }
} } t.printTable(10 }
0);
}
}
Output:
5
100
10
200
15
300
20
400
25
500
Java Synchronized Method
If you declare any method as synchronized, it is known as
synchronized method.
Synchronized method is used to lock an object for any shared
resource.
When a thread invokes a synchronized method, it automatically
acquires the lock for that object and releases it when the thread
completes its task.
Understanding the problem with Synchronization
public class
class Table{ class class TestSynchronization2{
synchronized void MyThread1 MyThread2 public static void
printTable(int n) extends
{//synchronized method
extends main(String args[]){
Thread{ Thread{ Table obj = new
for(int i=1;i<=5;i++){ Table t;
System.out.println(n*i); MyThread1(Ta Table t; Table();//only one
try{ ble t){ MyThread2(Ta object
Thread.sleep(400); this.t=t; ble t){ MyThread1 t1=new
}catch(Exception e) } this.t=t; MyThread1(obj);
{System.out.println(e);} public void } MyThread2 t2=new
}
run(){ public void MyThread2(obj);
}
t.printTable(5); run(){ t1.start();
}
} t.printTable(10 t2.start();
0); }
} } }
}
Output:
5
10
15
20
25
100
200
300
400
500
Points to Remember
Synchronized Block in
Java Synchronized block is used to lock an
object for any shared resource.
Synchronized block can be used to Scope of synchronized block is smaller
perform synchronization on any specific than the method.
resource of the method. A Java synchronized block doesn't allow
more than one JVM, to provide access
Suppose we have 50 lines of code in our control to a shared resource.
method, but we want to synchronize The system performance may degrade
only 5 lines, in such cases, we can use
synchronized block. because of the slower working of
synchronized keyword.
If we put all the codes of the method in Java synchronized block is more efficient
the synchronized block, it will work same than Java synchronized method.
as the synchronized method.
Example of Synchronized Block
class Table class MyThread1 class MyThread2 public class
{ extends Thread{ extends Thread{ TestSynchronizedBlo
void printTable(int n){
synchronized(this)
Table t; Table t; ck1{
{//synchronized block MyThread1(Tabl MyThread2(Table public static void
for(int i=1;i<=5;i++){ e t){ t){ main(String args[]){
System.out.println(n*i); this.t=t; Table obj = new
try{ this.t=t; Table();//only one
Thread.sleep(400); } } object
}catch(Exception e) public void run(){ public void run(){ MyThread1 t1=new
{System.out.println(e);} t.printTable(5);
} t.printTable(100); MyThread1(obj);
} } } MyThread2 t2=new
}//end of the method } MyThread2(obj);
} } t1.start();
t2.start();
}
}
Static Synchronization
If you make any static method as synchronized, the
lock will be on the class not on object.
Problem without static synchronization
Suppose there are two objects of a shared class (e.g.
Table) named object1 and object2. In case of
synchronized method and synchronized block there
cannot be interference between t1 and t2 or t3 and
t4 because t1 and t2 both refers to a common
object that have a single lock. But there can be
interference between t1 and t3 or t2 and t4 because
t1 acquires another lock and t3 acquires another
lock. We don't want interference between t1 and t3
or t2 and t4. Static synchronization solves this
problem.
Example of Static Synchronization
public class
class Table class MyThread1 class MyThread3 TestSynchronization4{
{ extends Thread{ extends Thread{ public static void main(String
public void run(){ t[]){
synchronized static void public void run(){ MyThread1 t1=new
Table.printTable(1); Table.printTable(100) MyThread1();
printTable(int n){ } MyThread2 t2=new
for(int i=1;i<=10;i++){ ; MyThread2();
} } MyThread3 t3=new
System.out.println(n*i); class MyThread2 MyThread3();
}
try{ extends Thread{ class MyThread4
MyThread4 t4=new
MyThread4();
Thread.sleep(400); public void run(){ extends Thread{ t1.start();
}catch(Exception e){} Table.printTable(10); public void run(){
t2.start();
t3.start();
} } Table.printTable(1000 t4.start();
} ); }
} }
} }
}