Day14_Multithreading_Executor_Framework_666015
Day14_Multithreading_Executor_Framework_666015
Multithreading In Java:
Multithreading is a programming concept in which the application can create a small unit of tasks to execute in
parallel. If you are working on a computer, it runs multiple applications and allocates processing power to them. A
simple program runs in sequence and the code statements execute one by one. This is a single-threaded application.
But, if the programming language supports creating multiple threads and passes them to the operating system to run
in parallel, it’s called multithreading.
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 areas so saves memory, and context-switching between the threads takes less time than
process.
1. It doesn't block the user because threads are independent and you can perform multiple operations at the
same time.
3. Threads are independent, so it doesn't affect other threads if an exception occurs in a single thread.
To develop animations
Multitasking:
Multitasking is the process of executing multiple tasks simultaneously. We use multitasking to utilize the CPU.
Multitasking can be achieved in two ways:
Each process has an address in memory. In other words, each process allocates a separate memory area.
A process is heavyweight.
Switching from one process to another requires some time for saving and loading registers, memory maps,
updating lists, etc.
A thread is lightweight.
Thread in java:
An application when it is under execution is called a process.
A thread is a separate flow of execution that execute some functionality of a program with the other part of the
program simultaneously.
Note: In Java, every program/application has a default flow of execution, a default thread, it is called the main
thread. if we can start another flow of execution(another thread) along with the main thread simultaneously
then it is called a multithreaded application or program.
Thread class and Runnable interface are the two structures using which we implement Thread based
multitasking in java.
The signature of a function using which we implement a thread is defined in an interface by the name Runnable.
This Runnable interface belongs to java.lang package. it has only one abstract method:
Inside this run() method we need to define the functionality, that we want to execute as a thread along with the main
thread. after providing the body we need to execute this functionality as a thread (i.e. simultaneously with the other
part of the program)
There is a class by the name Thread present in java.lang package, which has a method called start(), this start()
method is used to execute a given functionality defined inside the run() method of Runnable interface as a separate
thread.
This start() method of the Thread class recognize the run() method of the Runnable interface and then the run()
method is executed as a separate individual thread.
Example:
@Override
public void run(){
//define the taks which we want to execute as a thread
}
}
//or
Note: Internally the Thread class implements the Runnable interface and override run() method with empty
implementation.
Note:-weather we extends Thread class or implement Runnable interface directly, we have to use run()
method of the Runnable interface.
@Override
public void run(){
for(int i=0;i<30;i++){
System.out.println("inside run mehod "+i);
}
System.out.println("end of run() method");
}
X x1=new X();
for(int i=25;i<60;i++){
System.out.println("inside main mehod"+i);
}
System.out.println("end of main()..");
}
}
Here functionality of the start() method is to pick the run() method present in the object on which the start() method is
called and to handover this run() method to the thread-scheduler for the Scheduling.
Control will be in the main() method and other statements of main() will be executed simultaneously along with run()
method.
Since both the threads are getting executed simultaneously, the start/end execution of a thread completely depends
on the time slice allocated for each method thread
Hence without executing thread class start() method there is no chance of starting new thread in Java.
After starting a thread we are not allowed to restart the same thread once again otherwise we will get a runtime
exception called IllegalThreadStateException.
class Main {
t1.start();
t2.start();
t3.start();
If we extends Thread class to create a new thread then we loose the chance of Object Orientation biggest advantage
of inheritance i.e. we cannot extends another class simultaneously.
then supply the object of that class to the Thread class constructor and create Thread class object and start that
thread.
for(int i=20;i<40;i++){
System.out.println("inside main of ThreadA:"+i);
}
}
}
In Java, a thread always exists in any one of the following states. These states are:
1. New state
2. Runnable state
3. Running state
4. Blocked state
5. Dead state
Thread class has provides following getter and setter methods to get and set name of a thread.
Example:
@Override
public void run() {
for(int i=0;i<20;i++){
String tname=Thread.currentThread().getName();
System.out.println(tname +" is running ");
}
}
}
@Override
public void run() {
for(int i=0;i<20;i++){
String tname=Thread.currentThread().getName();
System.out.println(tname +" is running ");
}
}
}
t1.setName("Raj");
t2.setName("simran");
t1.start();
t2.start();
}
}
Note:- in the above example, two separate thread executes on the two different objects simultaneously.
for(int i=0;i<25;i++){
String tname=Thread.currentThread().getName();
System.out.println(tname +": is running");
}
}
one.setName("Dhoni thread..");
two.setName("Kohli thread..");
one.start();
two.start();
}
}
Here also, if we run the program multiple time, we can’t predict the output.
Thread Priorities:
Every thread in java has some priority. it may be default priority generated by the JVM or explicitly provided by
programmer.
Note :- priority should be assigned to the corresponding thread before calling the start() method.
1. Thread.MAX_PRIORITY---->10
2. Thread.MIN_PRIORITY---->1
3. Thread.NORM_PRIORITY--->5
Thread scheduler will use these priorities while allocating processer to our thread.
The thread which is having highest priority will get chance first.
If two threads having the same priority then we can't expect the exact execution order.it depends on the thread
scheduler.
2. public final void setPriority(int priority); it allows values from 1 to 10 otherwise we will get a runtime exception.
Note:-the default priority for main thread is 5 and for all remaining thread it will be inherited from parent to child.
A high priority thread does not run faster than lower priority thread.
Thread priority is not a rule for thread-scheduler, it is just a hint. so no guarantee for the execution (it will work only if
thread is in the waiting state or if there is a limited CPU time).
• If we are using thread priority for thread scheduling then we should always keep in mind that the underlying
platform should provide support for scheduling based on thread priority.
Example:
t1.setPriority(2);
t2.setPriority(5);
t3.setPriority(8);
Thread.currentThread().setPriority(10);
Suspending a thread:
For that purpose, we have some functionality(methods) inside the Thread class which helps us in gaining partial
control over the execution of run() method which are already scheduled by the thread-scheduler.
A thread which is already under execution can be suspended (prevented from getting executed further) or we can
control their execution based on three criteria:
1. Time
2. Conditionally
3. Unconditionally.
The main reason is that there's no-one to catch the exception, except for any catch-all handlers you might register
with your Thread or the containing ThreadGroup
Example:
@Override
public void run() {
System.out.println("end of run()...");
}
t1.start();
System.out.println("end of main()...");
If we want to suspend a running thread conditionally then we should use join() method of the Thread class.
If a thread t1 calls join() method on another thread t2, like t2.join() then t1 thread will be enter into waiting state
until t2 thread completes.
now if we have a condition that inside run() method of t1 we need to use some of the values calculated in run()
method of t2,then in this case we have to stop the execution of run() method of t1 until the run() method of t2 is
completely executed. in such situation we have to make use of join() method.
Here t2 thread will wait until completion of t1 thread and t3 thread will wait until the completion of t2 thread.
I Problem:
Let’s take a thread that will calculate the sum of 1 to 10 number, and another thread (main thread) will print the
calculated sum value of first thread.
int sum;
class Main {
A a1 = new A();
t.start();
}
}
}
Thread-safety in Java:
The concept of avoiding multiple threads acting upon the same functionality simultaneously is known as Thread-
safety.
If multiple threads are trying to operate simultaneously on the same functionality then there may be a chance of data
inconsistency problem.
Concurrency issue lead to the race-condition. and race-condition lead to the data inconsistency.
Race-condition:
Java is a multi-threaded programming language and there is a higher risk to occur race conditions. Because the
same resource may be accessed by multiple threads at the same time and may change the data.
A race-condition is a condition in which the critical section (a part of the program where shared memory is accessed)
is concurrently executed by two or more threads. It leads to incorrect behavior of a program.
In layman terms, a race condition can be defined as, a condition in which two or more threads compete together to
get certain shared resources.
For example, if thread A is reading data from the linked list and another thread B is trying to delete the same data.
This process leads to a race condition that may result in run time error
Example:
class Common{
public void fun1(Stirng name){
System.out.print("Welcome");
try{
Thread.sleep(1000);
}
catch(Exception ee){
}
System.out.println(name);
the above method fun1() is supposed to give the output as hello and after one second print the supplied name.
Now what will happen if two threads acts on this fun simultaneously.
Common c;
String name;
@Override
public void run() {
c.fun1(name);
}
}
Common c;
String name;
@Override
public void run() {
c.fun1(name);
}
}
class Main{
t1.start();
Now the output will be hello hello Ram Shyam which is not expected.
We can get the desired output if we avoid two thread acting on fun1() simultaneously.
To achieve this requirement we need to make fun1() as synchronized.
Note: The synchronized keyword applicable only for methods and blocks but not for variables and classes.
If a method or block is declared as synchronized then at a time only one thread is allowed to execute that method or
block on a given object so that data inconsistency problem will be resolved.
The main advantage of the synchronized keyword is we can resolve data inconsistency problem. but the main
disadvantage of the synchronized keyword is it increases waiting time of the threads and creates performance
problem on it. hence if there is no specific requirement then it is never recommended to use the synchronized
keyword.
Example:
checking seat availability method should be non-synchronized, where as book seat method should be
synchronized
Any method that changes the state of an object. i.e. add/update/delete/replace method we should use as
synchronized.
Synchronization concept:
Internally synchronization concept is implemented by using lock concept.
Every object in a java has a unique lock. most of the time the lock is unlocked.
When an object has one or more synchronized methods ,a thread can enter into a synchronized method or block
only when If that thread have the lock of that object.
The locks are not per methods basis, instead they are per object basis.
The thread won't release the lock until it completes the synchronized methods, so while that thread is holding the
lock of that object. once a synchronized method execution completed then thread releases the lock automatically.
Until the lock is released (completion of synchronized method.)no other threads can enter any of the
synchronized methods or blocks of that object.
So if an object has synchronized methods or blocks, a threads can enter any one of the synchronized methods or
block only if the lock of that object is available.
Acquiring and releasing the lock internally taken care by JVM, programmer are not responsible for this activity.
Note: while one thread is executing any one synchronized method on the given object then the remaining threads are
not allowed to execute any other synchronized method simultaneously. but remaining threads are allowed to execute
Example:
class A{
synch funA(){}
synch funB(){}
funC(){}
Here if one thread try to execute funA on A class object then it needs the lock of that object, once it acquires the lock
it starts the execution of that method funA, while executing funA by one thread, other threads are not allowed to
execute funA and even funB() also, but other threads can executes funC() simultaneously.
Example:
class Test{
t1.start();
t2.start();
}
}
But if we mark the synchronized fun1() method of class Common as "static" then we will get the regular output
irrespective of multiple objects also.
The reason behind this is because :
In java as there is a unique lock for each object of a class, similarly there is a unique lock for each class also.
So there are two types of lock in java:
If a thread try to execute a static synchronized method then it required class level lock.
object lock and class level lock both are independent and there is no link between them.
While a thread is executing a static synchronized method, the remaining threads are not allowed to execute any other
static synchronized method of that class simultaneously (**even on the multiple object of that class also)
but remaining threads are allowed to execute normal static and synchronized non-static methods and normal non-
static methods simultaneously.
Synchronized block:
If very few lines of the code requires synchronization then it is not recommended to declare entire method as
synchronized. we have to enclose those few lines of the code in synchronized block.
In a method, assume 10000 lines code is there, and in the middle somewhere few line need some Database
operation like(update/delete/add) then declaring entire method as synchronized is a worst kind of programming. here
it degrades the performance.
The main advantage of synchronized block over synchronized method is ,it reduces the waiting time of the threads
and improves the performance of the application.
void fun1(){
System.out.println("do something...");
synchronized(this){--//here if a thread gets the lock of current obj then it is allowed to execute
//this block
System.out.println("do some more thing1");
}
Example:
void fun1(){
System.out.println("do something...");
I Problem:
Race Condition Demo
package week4.day3;
//incrementing
this.increment();
System.out.println("Value for Thread After increment " + Thread.currentThread().getName() + " " + this.g
etValue());
//decrementing
this.decrement();
System.out.println("Value for Thread at last " + Thread.currentThread().getName() + " " + this.getValue
}
}
}
class RaceConditionDemo
{
public static void main(String args[])
{
Counter counter = new Counter();
Thread t1 = new Thread(counter, "Thread-1");
Thread t2 = new Thread(counter, "Thread-2");
Thread t3 = new Thread(counter, "Thread-3");
t1.start();
t2.start();
t3.start();
}
}
class Common {
synchronized(this){
System.out.print("Welcome :");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name);
}
}
}
Whenever we need to suspend a synchronized thread unconditionally then we use wait() method.
Whenever we need to resume a suspended(waiting) thread then we use notify() method.
Note:- we can call wait(), notify(),notifyAll() only in the synchronized block or synchronized methods.
otherwise we will get a runtime exception.
To call wait() or notify() method on any object we must have that particular object lock otherwise we will get a
runtime exception called IllegalMonitorStateException.
Once a thread calls wait() method on any object, first it releases the lock immediately of that particular object and
then it enters into the waiting state immediately.
Once a thread calls notify() method on any object it also releases the lock of that object but not immediately.
Wait and notify or notifyAll method belongs from Object class because "a thread" can call these methods on any
java object.
Example:
int total=0;
for(int i=0;i<=100;i++){
total=total+i;
}
}
}
class Main{
mt.start();
System.out.println(mt.total);
}
}
Here the main method of class Main is requires updation and here MyThread class run method performing
updation,
1. either main thread calls the sleep() method, so our main thread will enter into sleep state and other thread
perform complete operation.
but it is not recommended because if updation is completed in nano second then extra time will be wasted. or
if the updation will take too much time then we will get intermediate value.
2. main thread calls mt.join() method here until the run() method of MyThread completely finished main thread
will be in waiting state. and suppose if 10 thousand lines are there after that for loop then main has to wait till
all the lines of run method completely executes.
3. main thread calls the wait() method on the mt obj ,but remember if main thread try to call wait method then
main thread must have the lock of mt obj. otherwise we gets an exception.
Solution :
int num=0;
@Override
public void run() {
synchronized (this) {
}
}
class Test{
mt.start();
mt.wait();
System.out.println(mt.num);
Note:-In the above example most of the time main thread gets the chance first but if we call Thread.sleep()
method after the mt.start() then child thread gets the chance and the main thread will go to the waiting state
forever, to solve this problem we can use wait(5000) i.e.wait till 5sec.
You Problem:
Write the fun1() method of Common class using synchronized block to get the Class level lock.
Deadlock:
A lock without key is nothing but deadlock.
If two threads are waiting for each other forever(for infinite time).
The synchronized keyword is the only reason for deadlock.
There is no any solution for the deadlock but there are several prevention is there.
Example:
class A {
System.out.println("funA of A starts");
b1.fun2();
System.out.println("funA of A ends");
class B {
System.out.println("funB of B starts");
a1.fun1();
System.out.println("funB of B ends");
}
A a1;
B b1;
@Override
public void run() {
a1.funA(b1);
}
}
A a1;
B b1;
@Override
public void run() {
b1.funB(a1);
}
}
class Main {
public static void main(String[] args) {
A a1 = new A();
B b1 = new B();
t1.start();
t2.start();
Here if any method of class A or class B we remove the synchronized keyword then it will not become deadlock.
thread.start();
Creating a new thread for every task may creates performance and memory problems, to overcome this we
should go for Thread pool.
Without Thread pool, if we have 10 different independent tasks are there then we need to create 10 separate
threads.
But using Thread pool concept ,we create a Thread pool of 5 threads and submit all the 10 tasks to this Thread
pool.
Here a single thread can perform multiple independent tasks. so that performance will be improved.
ExecutorService service=Executors.newFixedThreadPool(3);
String name;
PrintJob(Sting name){
this.name=name;
}
try{
Thread.sleep(5000);
}catch(InturreptedException e){
e.printStackTrace();
}
class Main{
public static void main(String[] args){
PrintJob[] jobs={
new PrintJob("Ram"),
new PrintJob("Ravi"),
new PrintJob("Anil"),
new PrintJob("Shiva"),
new PrintJob("Pawan"),
new PrintJob("Suresh")
};
for(PrintJob job:jobs){
service.submit(job);
}
Note:- the object of Callable we can't pass to the normal Thread class constructor unlike Runnable
object, here we need to use the ExecutorService class help.
if we submit a Callable object to ExecutorService object, then after completing the task, thread returns an object
of the type Future.
The Future object can be used to retrieved the result from the Callable tasks.
Example:
import java.util.concurrent.*;
class MyCallable implements Callable{
int num;
@Override
public Object call() throws Exception {
int sum=0;
for(int i=0;i<=num;i++){
sum = sum+i;
}
return sum;
}
class Main{
MyCallable[] jobs = {
new MyCallable(10),
new MyCallable(20),
new MyCallable(30),
new MyCallable(40),
new MyCallable(50),
new MyCallable(60),
};
ExecutorService service=Executors.newFixedThreadPool(3);
for(MyCallable job:jobs){
Future f= service.submit(job);
System.out.println(f.get());
}
service.shutdown();
}
only one method public void run() only one method public Object call() throws Exception
if any exception raise compulsory we need to handle within try catch. not required to use try-catch
[Further Reading]
Suspending a thread unconditionally:
yield() method:
This yield() method is a static method defined inside the Thread class, it is used to pause the current executing
thread for giving the chance to remaining waiting thread of same priority, if there is no any waiting thread or all waiting
threads have low priority then same thread will get the chance once again for the execution.
suspend() method:
In order to suspend a thread unconditionally, we make use of non-static method suspend() present in a Thread class.
resume() method:
In order to resume a thread which has been suspended long back we use resume() method, it is also a non-static
method defined inside the Thread class.
Note: suspend() and resume() method are deprecated methods. we should not use those methods. we should not
use any deprecated methods.
The alternate methods are wait() and notify(). these methods are the non-static method defined inside the Object
class.
The wait() method will suspend a thread till notify() method is called, whereas yield() method says right now it is not
important please give the chance to another thread of same priority.