Multi Threading
Multi Threading
Contents
1 Introduction ..................................................................................................................................................................... 2
2 Ways to define a Thread ................................................................................................................................................. 4
2.1 By Implementing Thread class ................................................................................................................................ 4
2.2 Thread Schedular..................................................................................................................................................... 4
2.3 By Implementing Runnable Interface. .................................................................................................................... 8
2.4 Which approach is best to define a Thread and why? ......................................................................................... 10
2.5 Thread class constructors...................................................................................................................................... 10
3 Getting and Setting name of a Thread. ......................................................................................................................... 11
4 Thread Priorities. ........................................................................................................................................................... 12
4.1 Default Priority ...................................................................................................................................................... 13
5 The Methods to prevent thread execution. ................................................................................................................. 15
5.1 yield() ..................................................................................................................................................................... 15
5.2 join()....................................................................................................................................................................... 16
5.2.1 What is the impact of join() on thread life cycle? ........................................................................................ 18
5.3 sleep() .................................................................................................................................................................... 20
5.3.1 How a Thread can interrupt another Thread? ............................................................................................. 21
6 Synchronization ............................................................................................................................................................. 23
6.1 lock ......................................................................................................................................................................... 24
6.2 Synchronized Block................................................................................................................................................ 37
7 Interview Questions ...................................................................................................................................................... 41
8 Inter Thread Communication ........................................................................................................................................ 42
8.1 wait(), notify() & notifyAll() .................................................................................................................................. 42
8.2 Producer Consumer Problem ................................................................................................................................ 48
8.3 Difference between notify() and notifyAll() ......................................................................................................... 49
9 Deadlock ........................................................................................................................................................................ 49
9.1 Deadlock vs Starvation .......................................................................................................................................... 52
10 Daemon Threads ....................................................................................................................................................... 52
10.1 Default nature of Thread ...................................................................................................................................... 52
11 Mutlithreading Models ............................................................................................................................................. 54
12 How to stop a Thread ................................................................................................................................................ 55
13 Mutlithreading Enhancement ................................................................................................................................... 57
13.1 Thread Groups ....................................................................................................................................................... 57
1 Introduction
1. Multitasking: -
a. Executing several tasks simultaneously is the concept of multitasking.
2. There are two types of Multitasking: -
a. Process Based Multitasking
b. Thread Based Multitasking
3. Process Based Multitasking: -
a. Executing several tasks simultaneously where each task is separate
independent program (process) is called Process based multitasking.
Example: -
While typing a java program into the editor, we can listen to music from the
same system and download a file from the Internet. All of these tasks will be
completed simultaneously and independently of one another. As a result,
process-based multitasking is best suited at the operating system level.
4. Thread Based Multitasking: -
a. Executing several tasks simultaneously where each task is a separate
independent part of same program.
b. Thread based multitasking is best suitable at programmatic level.
c. Whether it is process based or Thread based the main objective of
Multithreading is to reduce response time & improve performance of the
system.
d. The main important applications of Multithreading are: -
i. To develop Multimedia graphics.
ii. To develop Animation.
iii. To develop video games.
b. In the case of t.start() method a new Thread will be created which is responsible
for the execution of run() method.
c. But in the case of t.run() method a new Thread will not be created & run() will be
executed just like a normal method call by Main Thread. Hence, in the above
program if we replace t.start() with t.run() then the output is “child thread 10
times followed by main thread 10 times this total output will be produced by
only main thread”.
3. Case 3: -
a. Importance of Thread class start(): -
i. Thread class start() is responsible to register the thread schedular and all
the mandatory activities hence without executing thread class start()
there is no chance of starting a new thread in Java. Due to this thread
class start() is considered as heart of Multithreading.
4. Case 4: -
a. It is always possible but thread class start() method can invoke no argument run()
other than overloaded method we have to call explicitly like a normal method call.
package com.MutliThreading;
Output: -
8. Case 8: -
a. Thread life cycle: -
9. Case 9: -
a. After starting a thread, if we are trying to restart the same thread then we will get
runtime exception saying IllegalThreadStateException.
3. Case study: -
MyRunnable r = new MyRunnable();
Thread t1 = new Thread();
Thread t2 = new Thread(r);
a. Case 1: -
t.start();
i. A new Thread will be created and which is responsible for the creation of
Thread class run(), which has empty implementation.
b. Case 2: -
t.run();
i. No new Thread will be created Thread class run() will be executed just like
a normal call.
c. Case 3: -
t2.start();
i. A new Thread will be created which is responsible for the execution of
MyRunnable class run().
d. Case 4: -
t2.run();
i. A new Thread will not be created and MyRunnable run() will be executed
just like a normal method call.
e. Case 5: -
r.start();
i. We will get compile time error saying MyRunnable class does not have
start capability.
CE: Cannot find Symbol
Symbol: Method start()
Location class MyRunnable
f. Case 6: -
r.run();
i. No new Thread will be created and runnable run() will be executed like
normal method call.
2.4 Which approach is best to define a Thread and why?
1. In the first approach our class always extends Thread class, there is no chance of
extending other class. Hence, we are missing Inheritance benefit.
2. But, in the second approach while implementing Runnable Interface we can extend
any other class. Hence, will not miss any Inheritance benefit because of above
reason, implementing Runnable interface is recommended than extending Thread
class.
2.5 Thread class constructors
1. Thread t = new Thread();
2. Thread t = new Thread(Runnable r);
3. Thread t = new Thread(String name);
4. Thread t = new Thread(Runnable r, String name);
5. Thread t = new Thread(ThreadGroup g, String name);
6. Thread t = new Thread(ThreadGroup g, Runnable r);
7. Thread t = new Thread(ThreadGroup g, Runnable r, String name);
8. Thread t = new Thread(ThreadGroup g, Runnable r, String name, long stacksize);
package com.MutliThreading;
}
public class ThreadDemo6 {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
//Output --> main
MyThread7 t = new MyThread7();
System.out.println(t.getName());
//Output --> Thread - 0
Thread.currentThread().setName("Pawan Kalyan");
System.out.println(Thread.currentThread().getName());
//Output --> Pawan Kalyan
System.out.println(10/0);
/* Exception in thread "Pawan Kalyan"
java.lang.ArithmeticException: / by zero
at com.MutliThreading.ThreadDemo6.main(ThreadDemo6.java:16)
*/
}
}
Output: -
main
Thread-0
Pawan Kalyan
Exception in thread "Pawan Kalyan" java.lang.ArithmeticException: / by zero
at com.MutliThreading.ThreadDemo6.main(ThreadDemo6.java:16)
1. Every Thread in java has some name it may be default name generated by JVM or
customized provided by programmer.
2. We can get and set name by using Thread class methods.
a. public final String getName();
b. public final void setName();
package com.MutliThreading;
4 Thread Priorities.
1. Every Thread in java has some priority, it may be default priority generated by JVM or
Customized priority provided by programmer.
2. The valid range of Thread priority is 1 to 10, where 1 is the Minimum priority & 10 is
Maximum priority.
3. Thread class defines the following constants to represent some standard priorities.
a. Thread.MIN_PRIORITY → 1
b. Thread.NORM_PRIORITY → 5
c. Thread.MAX_PRIORITY → 10
package com.MutliThreading;
class MyThread10 extends Thread {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Child thread");
}
}
}
public class ThreadDemo9 extends Thread {
public static void main(String[] args) {
ThreadDemo9 t = new ThreadDemo9();
t.setPriority(10); // Line - 1
t.start();
for (int i = 0; i < 10; i++) {
System.out.println("Main thread");
}
}
}
Output: -
Main thread
Main thread
Main thread
Main thread
Main thread
Main thread
Main thread
Main thread
Main thread
Main thread
Child thread
Child thread
Child thread
Child thread
Child thread
Child thread
Child thread
Child thread
Child thread
Child thread
3. If we are commenting Line 1 then both main and child threads have the same priority
5 and hence, we cannot expect execution order and exact output.
4. If we are not commenting Line 1 then main thread has the priority 5 and child has the
priority 10.
5. Hence, Child Thread will get the chance first followed by Main Thread.
Child thread
Child thread 10 times
Followed by main thread
main thread 10 times
Some platform will not provide proper support for thread priorities.
1. The yield() method causes the current executing thread to pause in order to give the
opportunity to a waiting thread with the same priorities.
2. If there are no waiting threads or all waiting threads have no priorities then same
thread can continue its execution.
3. If multiple threads are waiting with same priority, then we cannot expect and its
execution order depends on Thread schedular.
4. The Thread which is yielded (means left the processor), it will get the chance once
again and it depends on Thread schedular and we can’t expect exactly.
public static native void yield();
5. Thread Life cycle: -
6. Thread.yield() → Causes to pause current executing thread to give the chance for
remaining threads of same priority for that purpose we can use yield() method.
package com.MutliThreading;
3. If t1 executes t2.join() then immediately t1 will be entered into waiting state until t2
completes. Once t2 completes then t1 can complete its execution.
4. Wedding card printing thread t2 has to wait until venue fixing thread t1 completion.
Hence, t2 has to call join method. Wedding card distribution thread t3 has to wait
until Wedding card printing thread t2 completion. Hence, t3 has to call t2.join()
method.
5. There are 3 join methods: -
public final void join(); throws InterruptedException
public final void join(long ms); throws InterruptedException
public final void join(long ms, int ns); throws InterruptedException
6. Note: - Every join method throws InterruptedException which is checked Exception.
Hence, compulsory we should handle this Exception either by using try-catch or
throws keyword otherwise we will get Compile time Error.
7. Thread life cycle: -
}
}
}
package com.MutliThreading;
6 Synchronization
1. The synchronized modifier is only applicable to methods and blocks, not classes and
variables.
2. If multiple Threads attempt to operate on the same Java object at the same time, there
is a risk of data inconsistency. To avoid this, we should use the synchronized keyword.
3. If a method or block is declared as synchronized, only one Thread may execute that
method or block at a time. As a result, the issue of data inconsistency will be resolved.
4. The main advantage of the synchronized keyword is that it allows us to resolve data
inconsistency issues, but the main disadvantage is that it increases the waiting time of
Threads and causes performance issues. As a result, if there is no specific requirement,
the synchronized keyword is not recommended.
6.1 lock
1. Lock is used internally to implement the synchronization concept. Every object in Java
has a unique lock, and when we use the synchronized keyword, only the lock concept
comes into play.
2. If a Thread wants to execute a synchronized method on a given object, it must first
obtain Lock on that object. Once Thread has obtained the Lock, it is free to execute any
synchronized method on that object.
3. Thread will automatically release the Lock once method execution is complete. Internal
acquisition and release are handled by the JVM, and the programmer is not responsible
for this activity.
class Display {
public void wish(String name) {
for (int i = 0; i < 10; i++) {
System.out.print("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name);
}
}
}
@Override
public void run() {
d.wish(name);
}
class Display {
public void wish(String name) {
for (int i = 0; i < 10; i++) {
System.out.print("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name);
}
}
}
@Override
public void run() {
d.wish(name);
}
}
class Display {
public void wish(String name) {
for (int i = 0; i < 10; i++) {
System.out.print("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name);
}
}
}
class Display {
public void wish(String name) {
for (int i = 0; i < 10; i++) {
System.out.print("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name);
}
}
}
@Override
public void run() {
d.wish(name);
}
}
class Display {
public synchronized void wish(String name) {
for (int i = 0; i < 10; i++) {
System.out.print("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name);
}
}
}
@Override
public void run() {
d.wish(name);
}
}
package com.MutliThreading;
class Display {
public synchronized void wish(String name) {
for (int i = 0; i < 10; i++) {
System.out.print("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name);
}
}
}
@Override
public void run() {
d.wish(name);
}
}
11. Even though the .wish() method is synchronized in the above program, we will get
irregular output because Threads are operating on different objects. Reason,
Synchronization is required when multiple Threads operate on the same Java object.
Synchronization is not required when multiple Threads operate on multiple Java
objects.
12. Below program demonstrates the behavior of static synchronized methods, which lock
on the class object itself, ensuring that only one thread can access any static
synchronized method of that class at a time.
package com.MutliThreading;
class Display {
public static synchronized void wish(String name) {
for (int i = 0; i < 10; i++) {
System.out.print("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name);
}
}
}
@Override
public void run() {
d.wish(name);
}
}
17. While a Thread is executing static synchronized method the remaining Threads are not
allowed to execute any static synchronized method of that class simultaneously, but
remaining Threads are allowed to execute the following methods simultaneously.
a. Normal static()
b. Synchronized instance()
c. Normal instance()
package com.MutliThreading;
class Display2 {
public synchronized void displayN() {
for (int i = 0; i < 10; i++) {
System.out.print(i + " ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
}
}
public synchronized void displayC() {
for (int i = 65; i < 75; i++) {
System.out.print((char)i + " ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
}
}
}
package com.MutliThreading;
class Display3 {
// ;;;;;;;;;;1 lakh lines of code
public void wish(String name) {
for (int i = 0; i < 10; i++) {
System.out.println("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name);
}
}
// ;;;;;;;;; l Lakh of code
}
package com.MutliThreading;
class Display3 {
public void wish(String name) {
// l Lakh Lines of code
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.print("Good Morning: ");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name);
}
}
}
}
class Display4 {
public void wish(String name) {
// 1 Lakh lines of code
int x = 10;
synchronized (x) {
}
}
}
at com.MutliThreading.Display4.wish(SynchronizedDemo5.java:7)
at
com.MutliThreading.SynchronizedDemo5.main(SynchronizedDemo5.java:16)
7. Lock concept is applicable for object types & class types but not for primitive
arguments to synchronized block otherwise we will get compile time Error saying
unexpected type found in required reference.
7 Interview Questions
1. What is synchronized keyword and where it is used?
synchronized is a modifier applicable for methods & blocks but not for class.
2. Explain advantage of synchronized keyword?
We can resolve data inconsistency problem.
3. Explain disadvantage of synchronized keyword?
It increases waiting time of the Thread and creates performance problem.
4. What is race condition?
If multiple Thread are working or operating simultaneously then there may be a
chance of data inconsistency problem.
5. How can we resolve race condition?
By using synchronized keyword.
6. What is object lock and where it is required?
Every object in Java has unique lock which is nothing but object lock wherever a
Thread wants to execute instance synchronized method then the object requires
object block.
7. What is class level lock & where it is required?
The statements present in synchronized method & synchronized block are known as
synchronized statements.
1. Two Threads can communicate with each other by using wait(), notify() & notifyAll()
methods.
2. The thread that is expecting an update is responsible for calling the wait() method.
The Thread will then enter a waiting state immediately.
3. The thread that is responsible for updating; after updating, it is responsible for calling
the notify() method. The waiting Thread will then receive that notification and
resume its execution with the updated items.
8.1 wait(), notify() & notifyAll()
1. wait(), notify() & notifyAll() methods are present in which class?
They are present in Object class but not in Thread class.
2. Why these methods are present in Object class and not in Thread class?
wait(), notify() & notifyAll() methods are present in Object class and not in Thread
class. Because Thread can call these methods on any Java Object.
3. To call wait(), notify() & notifyAll() methods on any Object. Thread should be owner
of that Object i.e.; The Thread should be inside synchronized area. Hence, we can call
wait(), notify() & notifyAll() methods only from synchronized area. Otherwise, we
will get Runtime Exception saying IllegalMonitorException.
4. If a Thread calls .wait() method on any Object it immediately releases the lock of
that particular object & enters into waiting state.
5. When a Thread invokes notify() method on an Object, it releases the lock of that
Object, though the release might not occur immediately. Apart from wait(), notify()
& notifyAll() methods, no other method exists where a Thread releases the lock.
Methods Does Thread release the lock
yield() No
join() No
sleep() No
wait() Yes
notify() Yes
notifyAll() Yes
package com.MutliThreading;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
total += i;
}
}
}
package com.MutliThreading;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
total += i;
}
}
}
package com.MutliThreading;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
total += i;
}
}
}
package com.MutliThreading;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
total += i;
}
this.notify();
}
}
package com.MutliThreading;
package com.MutliThreading;
1. Producer Thread is responsible to produce items to the Queue and Consumer Thread
is responsible to consume items from the Queue.
2. If Queue is empty, then consumer thread will call wait() method and enters into
waiting state.
3. After Producing items to the Queue, producer thread is responsible to call notify()
method then waiting consumer will get that notification and continue its execution
with updated items.
8.3 Difference between notify() and notifyAll()
1. We can use notify() method to give notification to only one thread then only one
thread will be notified and the remaining threads have to wait for further
notification.
2. Which Thread will be notified, we cannot expect and it depends on JVM.
3. We can use notifyAll() method to give the notification to all the Threads of a
particular object, then even though multiple threads notified but execution will be
performed one by one because Threads require lock and only one lock is available.
9 Deadlock
1. If two Threads are waiting for each other forever such type of infinite waiting is
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 com.MutliThreading;
class A {
public synchronized void d1(B b) {
System.out.println("Thread 1 starts execution of d1() method");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println("Thread 1 trying to call B's Last()");
b.last();
}
10 Daemon Threads
1. The Threads which are executing in the background are called Daemon Threads.
E.g., Garbage collector, Attach listener & Signal dispatcher.
2. The main objective of Daemon Thread is to provide support for non-Daemon Threads
(Main Thread).
For E.g., If Main Thread runs with low memory, then JVM runs garbage collector to
destroy useless objects. So that number of bytes of free memory will be improved.
With this free memory main thread can continue its execution.
3. Usually, Daemon Threads have low priority but based on our requirement daemon
thread can run with high priority also.
4. We can check Daemon nature of a Thread by using isDaemon() of a Thread class.
5. We can change Daemon nature of a Thread by using setDaemon() method.
6. But changing Daemon nature is possible before starting of a Thread only after starting
a Thread if we are trying to change Daemon nature, then we will get
RuntimeException saying IllegalThreadStateException.
public boolean isDaemon()
public void setDaemon(boolean b)
10.1 Default nature of Thread
1. By default, Main Thread is always Non-Daemon and for all remaining threads
Daemon nature will be inherited from parent to child i.e., If parent thread is Daemon
then automatically child thread is also Daemon and if parent thread is Non-Daemon
then automatically child thread is also Daemon.
2. Note: - It is impossible to change Daemon nature of Main Thread because it is
already started by JVM at beginning.
package com.MutliThreading;
11 Mutlithreading Models
package com.MutliThreading;
package com.MutliThreading;
System.out.println(Thread.currentThread().getThreadGroup().getParent()
.getName());
}
}
Output
main
system
5. Every Thread in Java Belongs to some group, main thread belongs to main group.
6. Every Thread group in java is the child group of system group. Hence, system group
acts as root for all thread groups in java.
7. System group thread contains several system level threads like
a. finalizer
b. reference handler
c. signal dispatcher
d. attach listener etc.,
8. Thread Group is a Java class present in java.lang package and it is direct child class of
Object.
9. Constructors
a. ThreadGroup g = new ThreadGroup(String Groupname);
E.g.,
ThreadGroup g = new ThreadGroup(“First Group”);
Creates a new ThreadGroup with the specified group name. The parent of this
new Group is ThreadGroup of currently executing Thread.
package com.MutliThreading;