Multi Threading in Java by Durga Sir
Multi Threading in Java by Durga Sir
1. Introduction
2. The ways to define a thread
By extending a thread class
By implementing Runnable Interface
3. Getting and setting name of threads
4. Thread priorities
5. The method to prevent thread execution
Yield()
Join()
Sleep()
6. Synchronization
7. Interthread communication
8. Deadlock
9. Daemon thread
10. Multithreading enhancement
Introduction :
Multitasking :
Example:
1. While typing is a java program in the editor we can listen audio songs
from the same system.
2. At the same time we can download a file from internet. All these tasks
will be executed simultaneously and independent of each other. Hence it
is process based multi-tasking.
Defining a thread:
We can define a thread in the following two ways.
package demoThread;
// defining a thread
public class MyThread extends Thread {
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("child-thread"); // job of child thread
and executed by child thread
}
}
}
package demoThread;
after t.start()
Output:
main-child
main-child
main-child
main-child
main-child
child-thread
child-thread
child-thread
child-thread
child-thread
Thread scheduler:
It is the art of JVM and it is responsible to schedule threads i.e if
multiple threads are waiting to get the chance of execution then in which
order threads will be executed is decided by thread scheduler.
Case2:
But in the case of t.run() a new thread won’t be created and run() method
will be executed just like a normal method call by main thread.
package demoThread;
// defining a thread
public class MyThread extends Thread {
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("child-thread"); // job of child thread
and executed by main thread
}
}
}
package demoThread;
child-thread
child-thread
child-thread
child-thread
child-thread
main-child
main-child
main-child
main-child
main-child
Case3:
Start() {
}
Case4:
package demoThread;
package demoThread;
t.run(10);
}
}
Output:
int-arg
no-arg
Case5:
If we are not overriding run() method:
If we are not overriding run() method then Thread class run() method
will be executed which has empty implementation. Hence we won’t get any
output.
package demoThread;
package demoThread;
}
}
No output.
Case6:
package demoThread;
package demoThread;
System.out.println("main-method");
}
Output:
Note:
package demoThread;
package demoThread;
System.out.println("main-method");
}
}
Possible outputs:
Case8:
New/born
t.start();
ready/born
running
Dead
Case9:
After starting a thread if we are trying to re-start the same thread then we
will get RunTimeException saying IllegalThreadStateException.
package demoThread;
package demoThread;
t.start();
System.out.println("main-method");
}
Output:
Approach 1st:
Approach 2nd:
package demoThread;
package demoThread;
t1.start();
Possible outputs:
Case Study:
MyThread t1 = new MyThread();
Case2:
t2.run();--- No new thread will be created and Thread class run() will
be executed just like a normal method call.
Case3:
Case4:
Case5:
Case6:
t1.run();--- No new thread will be create and MyThread class run() method
will be executed just like a normal method call.
Answer:
package demoThread;
System.out.println("child thread");
}
}
package demoThread;
t1.start();
System.out.println("main Thread");
}
}
Possible output:
package demoThread;
package demoThread;
System.out.println(Thread.currentThread().getName());
Thread.currentThread().setName("Lalit Bizlain");
System.out.println(Thread.currentThread().getName());
System.out.println(10/0);
}}
Output:
main
Thread-0
Thread-1
Lalit Bizlain
Exception in thread "Lalit Bizlain" java.lang.ArithmeticException: /
by zero
at demoThread.ThreadDemo.main(ThreadDemo.java:18)
Note:
package demoThread;
@Override
public void run() {
System.out.println("run method executed by Thread " +
Thread.currentThread().getName());
}
}
package demoThread;
}
}
Output:
main method executed by Thread main
run method executed by Thread Thread-0
Thread Priorities:
Every Thread in java has some priority. It may be default priority
generated by JVM or customized priority provided by programmer.
Thread.MIN_PRIORITY = 1
Thread.NORM_PRIORITY = 5
Thread.MAX_PRIORITY = 10
Thread.LOW_PRIORITY
Thread.HIGH_PRIORITY
Thread.MIN_PRIORITY
Thread.NORM_PRIORITY
package demoThread;
t.setPriority(17);------------------invalid
}
}
The default priority only for the main Thread is 5. For all remaining
Threads default priority will be inherited from parent to child i.e
whatever priority parent Thread has, the same priority will be there
for the child Thread.
package demoThread;
package demoThread;
}
}
Output:
5
7
package demoThread;
@Override
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("child thread");
}
}
package demoThread;
}
}
Output:
Child thread
Child thread
Child thread
Child thread
Child thread
main thread
main thread
main thread
main thread
main thread
If we are commenting line 1 then both main and child threads have the same
priority 5 and hence we can’t expect execution order and exact output.
If we are not commenting line 1 then main thread has a priority 5 and child
thread has the priority 10. Hence child thread will get the chance 1 st
followed by main thread.
Yield() method
Join() method
Sleep() method
1.Yield() method:
Yield() method causes "to pause current executing Thread for
giving the chance of remaining waiting Threads of same priority".
If there is no waiting Thread or all waiting Threads are low
priority then same Thread can continue its execution.
If several waiting Threads with the same priority
available/waiting then we can't expect exact which Thread will
get chance for execution. It depends on Thread scheduler.
The Thread which is yielded when it gets chance once again for
execution. It depends on the mercy of the Thread scheduler.
New/born
t.start();
ready/runnable
running
dead
package demoThread;
@Override
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("child thread");
Thread.yield();------------------------1
}
}
package demoThread;
public class ThreadYieldDemo {
t.start();
}
}
Output:
main thread
main thread
main thread
main thread
child thread
main thread
child thread
child thread
child thread
child thread
In the above program if we are commenting line 1 then both threads will
be executed simultaneously and we can’t expect which Thread will
complete 1st.
If we are not commenting line 1 then child Thread always call yield()
method because of that main Thread will get chance more number of times
and the chance of completing main Thread 1st is high.
Some platforms won’t provide proper support for yield method.
2.Join() method:
If a Thread wants to wait until completing some other Thread then we
should go for join() method.
Example:
Wedding cards printing Thread (t2) has to wait until venue fixing
Thread (t1) completion. Hence t2 has to call t1.join().
Wedding cards distribution Thread (t3) has to wait until wedding
cards printing Thread (t2) completion. Hence t3 has to call
t2.join().
Note:
Every join method throws interrupted exception which is checked
exception. Hence compulsory we should handle this exception either by
try-catch or by throws keyword, otherwise we will get compile time
error.
New/born
t.start();
ready/runnable
running
dead
package demoThread;
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("sheeta thread");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
package demoThread;
t.start();
t.join();-------------------------1
}
}
If we comment line 1 then both main and child threads will be
executed simultaneously and we can’t expect exact output.
If we are not commenting line 1 then main thread calls method on
child thread. Hence main thread will wait until child thread
output is
Output:
sheeta thread
sheeta thread
sheeta thread
sheeta thread
sheeta thread
Ram thread
Ram thread
Ram thread
Ram thread
Ram thread
Example2: waiting Thread with time period or wait for some time either
another Thread complete or not.
package demoThread;
@Override
public void run() {
System.out.println("sheeta thread");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}
package demoThread;
t.start();
t.join(5000);--------------1
}
}
If we comment line 1 then both main and child threads will be
executed simultaneously and we can’t expect exact output.
If we are not commenting line 1 then main thread calls method on
child thread. Hence main thread will wait until child thread
output is
Output:
sheeta thread
sheeta thread
sheeta thread
Ram thread
Ram thread
Ram thread
Ram thread
Ram thread
sheeta thread
sheeta thread
package demoThread;
package demoThread;
MyThread.mt = Thread.currentThread();
MyThread t = new MyThread();
t.start();
}
}
In the above example child Thread calls join() method on main Thread
object. Hence child Thread has to wait until completing main Thread.
In this case output is
Output:
main thread
main thread
main thread
main thread
main thread
child thread
child thread
child thread
child thread
child thread
Example4:
If main Thread calls join() method on child Thread object and child
Thread call join() on main Thread object then both Threads will wait
forever and the program will be stuck (This is something like
Deadlock).
package demoThread;
package demoThread;
t.start();
t.join();
}
}
Example5:
If a Thread calls join() method on the same Thread itself then the
program will be stuck (This is something like Deadlock).
package demoThread;
Thread.currentThread().join();
}
}
Sleep() method
1. If a Thread don’t want to perform any performance for a particular
amount of time then we should go for sleep() method.
Note:
package demoThread;
}
}
Output:
slide 0
slide 1
slide 2
slide 3
slide 4
package demoThread;
public class MyThread extends Thread {
@Override
public void run() {
try {
for(int i = 0; i < 5; i++) {
System.out.println("I am Lazy Thread");
Thread.sleep(2000);
}
} catch (InterruptedException e) {
System.out.println("I got interrupted");
}
}
}
package demoThread;
t.interrupt();------------------1
Output:
Note:
1. Whenever we are calling interrupt() method, if the target Thread
not in sleeping state or waiting state then there is no impact of
interrupt call immediately. Interrupt call will be waited until
target Thread entered into sleeping or waiting state.
2. If the target Thread entered into sleeping or waiting state then
immediately will interrupt target Thread.
package demoThread;
@Override
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("I am Lazy Thread " + i);
}
}
}
package demoThread;
t.interrupt();
Synchronization:
1. Synchronized is the modifier applicable only for methods and blocks but
not for classes and variables.
2. If multiple Threads are trying to operate simultaneously on the same
java object then there may be a chance of data inconsistency problem.
3. To overcome this problem we should go for synchronized keyword.
4. If a method or block declared as synchronized then at a time only one
Thread is allowed to execute that method or block and given object. So
that data inconsistency problem will be resolved.
5. The main advantage of synchronized keyword is we can resolve data
inconsistency problems but the main disadvantage of synchronized
keyword is it increases waiting time of Threads and creates performance
problems. Hence if there is no specific requirement then it is not
recommended to use synchronized keyword.
6. Internally synchronization is implemented by using lock. Every object
in java has a unique lock.
7. Whenever we are using synchronized keyword then only lock concept will
come into the picture.
8. If a Thread wants to execute synchronized method on the given object,
1st it has to get lock of that object. Once Thread got the lock then it
is allowed to execute any synchronized method on that object.
9. Once method execution completes automatically Thread releases the lock.
10. Acquiring and releasing the lock, internally takes care by JVM
and programmer not responsible for this activity.
11. While a Thread executing synchronized method on the given object,
the remaining Threads not allowed to execute any synchronized method
simultaneously on the same object but remaining Threads are allowed to
execute non-synchronized method simultaneously.
package demoThread;
public class X {
void m3() {
m3()
t4
Object
Synchronized area:
Wherever we are performing update operation
(add/remove/delete/replace) where state of object changing.
update
Example:
Execution of wish method with synchronized keyword without
Thread:
package demoThread;
}
public static void main(String[] args) {
Display d = new Display();
d.wish("dhoni");
}
}
Output:
Good Morning:dhoni
Good Morning:dhoni
Good Morning:dhoni
Good Morning:dhoni
Good Morning:dhoni
package demoThread;
package demoThread;
Display d;
String name;
@Override
public void run() {
d.wish(name);
}
package demoThread;
}
}
Output:
Good Morning:Dhoni
Good Morning:Dhoni
Good Morning:Dhoni
Good Morning:Dhoni
Good Morning:Dhoni
package demoThread;
t1.start();
t2.start();
t3.start();
}
}
Output:
Good Morning:Good Morning:Good Morning:Kohli
Good Morning:Yuvraj
Good Morning:Dhoni
Good Morning:Kohli
Good Morning:Dhoni
Good Morning:Yuvraj
Good Morning:Dhoni
Good Morning:Kohli
Good Morning:Yuvraj
Good Morning:Dhoni
Yuvraj
Kohli
Good Morning:Good Morning:Good Morning:Dhoni
Yuvraj
Kohli
package demoThread;
package demoThread;
Display d;
String name;
@Override
public void run() {
d.wish(name);
}
package demoThread;
}
}
Output:
Good Morning:Dhoni
Good Morning:Dhoni
Good Morning:Dhoni
Good Morning:Dhoni
Good Morning:Dhoni
Good Morning:Kohli
Good Morning:Kohli
Good Morning:Kohli
Good Morning:Kohli
Good Morning:Kohli
Good Morning:Yuvraj
Good Morning:Yuvraj
Good Morning:Yuvraj
Good Morning:Yuvraj
Good Morning:Yuvraj
package demoThread;
}
public static void main(String[] args) {
Display d1 = new Display();
d1.wish("dhoni");
Display d2 = new Display();
d2.wish("Yuvraj");
Display d3 = new Display();
d3.wish("kohli");
}
}
Output:
Good Morning:dhoni
Good Morning:dhoni
Good Morning:dhoni
Good Morning:dhoni
Good Morning:dhoni
Good Morning:Yuvraj
Good Morning:Yuvraj
Good Morning:Yuvraj
Good Morning:Yuvraj
Good Morning:Yuvraj
Good Morning:kohli
Good Morning:kohli
Good Morning:kohli
Good Morning:kohli
Good Morning:kohli
package demoThread;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println(name);
}
}
package demoThread;
Display d;
String name;
@Override
public void run() {
d.wish(name);
}
package demoThread;
t1.start();
t2.start();
t3.start();
}
}
Output:
package demoThread;
package demoThread;
Display d;
String name;
@Override
public void run() {
d.wish(name);
}
package demoThread;
Output:
Good Morning:Good Morning:Good Morning:kohli
Good Morning:Dhoni
Good Morning:Yuvraj
Good Morning:kohli
Good Morning:Yuvraj
Good Morning:Dhoni
Good Morning:kohli
Good Morning:Dhoni
Good Morning:Yuvraj
Good Morning:Dhoni
Good Morning:Yuvraj
Good Morning:kohli
Good Morning:kohli
Dhoni
Yuvraj
Conclusion:
package demoThread;
public class X {
}
synchronized void m4() {
}
void m5() {
Waiting state
t2 m1() X t1—class level lock(x)
t3 m2()
m1(){ }
m3()
t4
m4() m5()
t5
t6
Example:
1. create only one object for multiple display without synchronized method
but with multiple Threads
package demoThread;
}
public void display2() {
for(int i = 65; i < 75; i++) {
System.out.print((char)i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
package demoThread;
Display d;
MyThread1 (Display d) {
this.d = d;
@Override
public void run() {
d.display1();;
}
package demoThread;
MyThread2(Display d) {
this.d = d;
}
@Override
public void run() {
d.display2();;
}
package demoThread;
0AB1C2D3E4F5G6H7I8J910111213141516171819202122232425
package demoThread;
}
public synchronized void display2() {
for(int i = 65; i < 75; i++) {
System.out.print((char)i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO: handle exception
}
}
package demoThread;
Display d;
MyThread1 (Display d) {
this.d = d;
@Override
public void run() {
d.display1();;
}
package demoThread;
MyThread2(Display d) {
this.d = d;
}
@Override
public void run() {
d.display2();;
}
package demoThread;
012345678910111213141516171819202122232425ABCDEFGHIJ
Synchronized block:
1. If very few lines of the code required synchronization then
it is not recommended to declare entire method as
synchronized. We have to enclose those few lines of the
code by using synchronized block.
2. The main advantage of the synchronized block over
synchronized method is, it reduced waiting time of Threads
and improves performance of the system/application.
3. We can declare synchronized block as follows:
2. To get lock of current object:
Synchronized(this){
Synchronized(b){
Synchronized(Display.class){
package demoThread;
}
System.out.println(name);
}
// 1 lacs coding lines
}
package demoThread;
Display d;
String name;
@Override
public void run() {
d.wish(name);;
}
package demoThread;
Output:
package demoThread;
Output:
package demoThread;
synchronized(Display.class) {
for(int i = 0; i < 5; i++) {
System.out.print("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println(name);
}
// 1 lacs coding lines
}
package demoThread;
Display d;
String name;
@Override
public void run() {
d.wish(name);
}
package demoThread;
Output:
Note:
Lock concept applicable for object types and class types but not for
primitives. Hence we can’t pass primitive type as argument to
synchronized block, otherwise we will get compile time error saying
unexpected type found int required references.
FAQs:
package demoThread;
public class X {
Y y = new Y();
synchronized (y) {
// here thread has lock of X and Y object
Z z = new Z();
synchronized (z) {
// here thread has lock of X,Y and Z object
}
}
}
}
package demoThread;
// Thread.sleep(1);
// for(int i = 0; i < 10; i++) {
// System.out.println(b.total);
// }
}
}
Output:
Queue
package demoThread;
package demoThread;
Synchronized(s1){
S2.wait();
}----wrong
Synchronized(s1){
S1.wait();
}----------right
Deadlock:
1. If two Threads are waiting for each other forever. Such type of
infinite waiting is called Deadlock.
2. Synchronized keyword is the only reason for Deadlock situation. Hence
while using synchronized keyword we have to take special care.
3. There are no resolution technique for Deadlock but several prevention
techniques are available.
package demoThread;
class A {
public synchronized void foo(B b) {
System.out.println("Thread1 starts execution of foo() method");
try{
Thread.sleep(2000);
}
catch (InterruptedException e)
{}
System.out.println("Thread1 trying to call b.last()");
b.last();
}
DeadLock() {
Thread t = new Thread(this);
t.start();
a.foo(b);// main thread
}
Output:
Daemon Threads:
The Threads which are executing in the background are called daemon Threads.
Example:
Garbage collector
Whenever the program runs with low memory the JVM will execute Garbage
Collector to provide free memory. So that the main Thread can continue
it's execution.
We can check whether the Thread is daemon or not by using isDaemon()
method of Thread class.
But we can change daemon nature before starting Thread only. That is
after starting the Thread if we are trying to change the daemon nature
we will get R.E saying IllegalThreadStateException.
Default Nature : Main Thread is always non daemon and we can't change
its daemon nature because it's already started at the beginning only.
Main Thread is always non daemon and for the remaining Threads daemon
nature will be inheriting from parent to child that is if the parent is
daemon child is also daemon and if the parent is non daemon then child
is also non daemon.
Whenever the last non daemon Thread terminates automatically all daemon
Threads will be terminated.
Example:
System.out.println(Thread.currentThread().isDaemon());
System.out.println(t.isDaemon());----------1
t.start();
t.setDaemon(true);
System.out.println(t.isDaemon());
Output:
false
false
RE:IllegalThreadStateException
Example:
package demoThread;
Output:
If we comment line 1 then both main & child Threads are non-Daemon ,
and hence both threads will be executed untill there completion.
If we are not comment line 1 then main thread is non-Daemon and child
thread is Daemon. Hence when ever main Thread terminates automatically
child thread will be terminated.
Lazy thread
If we are commenting line 1 then both main and child Threads are non
daemon and hence both will be executed until they completion.
If we are not commenting line 1 then main Thread is non daemon and
child Thread is daemon and hence whenever main Thread terminates
automatically child Thread will be terminated.
Deadlock vs Starvation:
We can call stop() method to stop a Thread in the middle then it will
be entered into dead state immediately.
stop() method has been deprecated and hence not recommended to use.
A Thread can suspend another Thread by using suspend() method then that
RACE condition:
ThreadGroup:
-----------
g.stop();
ThreadLocal(1.2 v):
We can use ThreadLocal to define local resources which are required for
a perticular Thread like DBConnections, counterVariables etc.
We can use ThreadLocal to define Thread scope like Servlet
Scopes(page,request,session,application).
GreenThread:
Java multiThreading concept is implementing by using the
following 2 methods :
1. GreenThread Model
2. Native OS Model
GreenThread Model
The threads which are managed completely by JVM without taking
support for underlying OS, such type of threads are called Green
Threads.
Native OS Model
The Threads which are managed with the help of underlying OS are
called Native Threads.
Windows based OS provide support for Native OS Model
Very few OS like SunSolaries provide support for GreenThread
Model
Anyway GreenThread model is deprecated and not recommended to
use.
Life cycle of a Thread:
class.
Runnable interface.
Example:
Example:
Step 1: Declare a boolean type variable and store false in that variable.
boolean stop=false;
Step 2: If the variable becomes true return from the run() method.
If(stop) return;
Step 3: Whenever to stop the Thread store true into the variable.
System.in.read();//press enter
Obj.stop=true;