The mechanism of
executing multiple threads simultaneously is known as multithreading. A thread
is a sequence of method calls within the program. Every thread is independent
and has its program counter, stack and local variable. In this tutorial, I am
going to cover all the concepts that are related to threads. We will cover what
are threads, Why do we need multithreading, how can we create threads, what is
the concept of threads, examples of multithreading in java.
What are the threads?
A Thread is a lightweight
process. They allow multiple tasks to be performed at the same time. All the
threads share the same address space. Since they share the same address they
can have common data and code.
What is the difference between threads and process?
1. A Thread is a part of a process whereas a
process is defined as a program in execution.
2. Each thread has its stack. Multiple threads
share the same address space of process whereas process has its address space.
3. Threads are lightweight whereas processes are
heavyweight
4. As threads are lightweight they have less
overhead as compared to the process.
5. For communication process uses Interprocess
communication whereas threads can communicate directly as they share the same
address.
The life cycle of a
thread
A thread goes through different stages during its life cycle. The below diagram shows different stages of the cycle.
Let us discuss these:
1. New - this stage is also referred to as a born stage.
This is the initial stage wherein a thread is created and will remain in this
thread until the program starts it.
2. Runnable - This stage comes when a thread starts its execution. This
stage comes when we call start().
3. Running - this stage comes when the thread scheduler selects the
thread. run() invokes this stage.
4. Waiting - from the running stage while the thread is running if we
can sleep() or wait() methods then this stage comes into the picture.
5. Dead - this stage comes when the thread execution is completed.
This stage is also known as the terminated stage.
Thread
priorities
To make the multiple
threads run in order the OS scheduler needs to divide the multiple threads
based on thread priority. Hence, to achieve this each thread is assigned with
its priority.
The range of priority is
defined by three variables i.e. MIN_PRIORITY, a constant of 1, MAX_PRIORITY, a
constant of 10 and NORM_PRIORITY, a constant of 5. By default, NORM_PRIORITY is
declared for every thread.
The threads which have
higher priority will be scheduled first as compared to lower priority threads.
However, the priority of a thread is not the sole reason for thread execution,
the operating system also plays a very big role.
How
to create a thread in java
There are mainly two
ways by which we can create a thread.
1. Implementing the runnable interface
2. Extending the thread class
There is a significant
difference in when to use which method. Consider the scenario in which the
class is already extending another class and as java does not support multiple
inheritance hence we will not be allowed to create a thread by extending the
class. Hence, in cases when the class is extending another class, we can create
a thread by implementing the runnable interface.
Also, if we know that
the class implementation is full and in future also we will not be extending
this class with another class then we can create the thread by extending the
thread class otherwise, we should implement the runnable interface.
Let’s discuss both these
ways in detail with an example:
Creating
thread by Implementing a runnable interface
Steps need to be
followed to create a thread using the runnable interface.
1. The runnable interface has run() method
which we need to implement into the class. This will create an entry point for
the thread. All the main logic which requires threading will be under this
method.
2. In the second step, we need to create the object
of the thread class using its default constructor
Thread(Runnable
Obj, String threadName)
The
obj should be the instance of the class which implements the runnable
interface.
- As
the last step, after the thread object is created, we need to call start() method
on the object of the runnable class. This will internally call the run() method.
Below is the example of creating and running a thread.
class RunnableExample implements Runnable{ | |
private Thread thread; | |
String threadName; | |
RunnableExample(String name){ | |
threadName = name; | |
System.out.println("Creating Stage: " + threadName); | |
} | |
public void run(){ | |
System.out.println("Running Stage"); | |
try{ | |
for(int i = 4; i> 0 ; i--){ | |
System.out.println("Thread : " + threadName + "," + i ); | |
Thread.sleep(50); | |
} | |
}catch(InterruptedException e){ | |
System.out.println("Thread : " + threadName + " interrupted"); | |
} | |
System.out.println("Thread : " + threadName + " exiting" ); | |
} | |
public void start(){ | |
System.out.println("Starting Stage : " + threadName); | |
if(t == null){ | |
t = new Thread(this, threadName); | |
t.start(); | |
} | |
} | |
} | |
public class ThreadTest{ | |
public static void main(String args[]){ | |
RunnableExample r1 = new RunnableExample("Thread t1"); | |
r1.start(); | |
RunnableExample r2 = new RunnableExample("Thread t2"); | |
r2.start(); | |
} | |
} |
Output:
Creating Stage Thread t1
Starting stage Thread t1
Creating Stage Thread t2
Starting stage Thread t2
Running Stage Thread t1
Thread: Thread t1,
4
Running Stage Thread t2
Thread: Thread t2,
4
Thread: Thread t1,
3
Thread: Thread t2,
3
Thread: Thread t1,
2
Thread: Thread t2,
2
Thread: Thread t1,
1
Thread: Thread t2,
1
Thread t1 exiting
Thread t2 exiting
Creating
a thread by extending thread class
Steps need to be
followed to create a thread by extending thread class
1. Thread class has an abstract run() method
which we need to override into the class. This will create an entry point for
the thread. All the main logic which requires threading will be under this
method.
2. As the last step, after the thread object is
created, we need to call start() method on the object of the
runnable class. This will internally call the run() method.
Below is the example of creating and running a thread.
class ThreadClassExample Extends Thread{ | |
private Thread thread; | |
String threadName; | |
ThreadClassExample(String name){ | |
threadName = name; | |
System.out.println("Creating Stage: " + threadName); | |
} | |
public void run(){ | |
System.out.println("Running Stage"); | |
try{ | |
for(int i = 4; i> 0 ; i--){ | |
System.out.println("Thread : " + threadName + "," + i ); | |
Thread.sleep(50); | |
} | |
}catch(InterruptedException e){ | |
System.out.println("Thread : " + threadName + " interrupted"); | |
} | |
System.out.println("Thread : " + threadName + " exiting" ); | |
} | |
public void start(){ | |
System.out.println("Starting Stage : " + threadName); | |
if(t == null){ | |
t = new Thread(this, threadName); | |
t.start(); | |
} | |
} | |
} | |
public class ThreadTest{ | |
public static void main(String args[]){ | |
ThreadClassExample r1 = new ThreadClassExample("Thread t1"); | |
r1.start(); | |
RunnableExample r2 = new RunnableExample("Thread t2"); | |
r2.start(); | |
} | |
} |
Output:
Creating Stage Thread t1
Starting stage Thread t1
Creating Stage Thread t2
Starting stage Thread t2
Running Stage Thread t1
Thread: Thread t1,
4
Running Stage Thread t2
Thread: Thread t2,
4
Thread: Thread t1,
3
Thread: Thread t2,
3
Thread: Thread t1,
2
Thread: Thread t2,
2
Thread: Thread t1,
1
Thread: Thread t2,
1
Thread Thread t1 exiting
Thread Thread t2 exiting
Important
Thread methods
Sr. No. |
Methods and Description |
1. |
public void start() |
2. |
public void run() |
3. |
public final void setName(String name) |
4. |
public final void setPriority(int priority) |
5. |
public final void setDeamon(boolean on) |
6. |
public final void join(long milisec |
7. |
public void interrupt() |
8. |
public final boolean isAlive() |
9. |
public static void yield() |
10. |
public static void sleep(long milisec) |
11. |
public static boolean holdsLock(Object x) |
12. |
public static Thread currentThread() |
13. |
public static void dumpStack() |
Inter-thread
Communication
Threads concept in java
provides a very seamless way so that threads can communicate with each other.
There can be scenarios where multiple threads want to share some information.
In this case, we need inter-thread communication.
Inter-thread
communication is also important to overcome Deadlock. Deadlock is the case when
multiple threads are waiting for the object access.
There are three methods
which facilitate inter-thread communication:
Sr. No. |
Methods and Description |
1. |
public void wait() |
2. |
public void notify() |
3. |
public void notifyAll() |
public void wait() -
takes the thread to wait for the state until notify() called.
public
void notify() - wakes the thread
on which wait() was called.
public
void notifyAll() - wakes all the
threads on which wait() was called.
All these methods are in
object class as they deal with objects and perform the operations on objects.
Hence, they are available in all the classes. Only synchronized context
can call these methods.
Let’s go through an example where two threads communicate with each other using wait() and notify().
class ChatExample{ | |
boolean flag = false; | |
public synchronized void Question(String msg){ | |
if(flag){ | |
try{ | |
wait(); | |
}catch(InterruptedException ex){ | |
e.printStackTrace(); | |
} | |
} | |
System.out.println(msg); | |
flag = true; | |
notify(); | |
} | |
public synchronized void Answer(String msg){ | |
if(!flag){ | |
try{ | |
wait(); | |
}catch(InterruptedException ex){ | |
e.printStackTrace(); | |
} | |
} | |
System.out.println(msg); | |
flag = false; | |
notify(); | |
} | |
} | |
class T1 implements Runnable{ | |
ChatExample m; | |
String[] s1 = {"Hi, How are you, I am fine"}; | |
public T1(ChatExample m1){ | |
this.m = m1; | |
new Thread(this, "Question").start(); | |
} | |
public void run(){ | |
for(int i = 0; i< s1.length; i++){ | |
m.Question(s1[i]); | |
} | |
} | |
} | |
class T2 implements Runnable{ | |
ChatExample m; | |
String[] s2 = {"Hi, I am good, What about you, Great"}; | |
public T2(ChatExample m2){ | |
this.m = m2; | |
new Thread(this, "Answer").start(); | |
} | |
public void run(){ | |
for(int i = 0; i< s2.length; i++){ | |
m.Answer(s2[i]); | |
} | |
} | |
} | |
public class ThreadTest{ | |
public static void main(String args[]){ | |
ChatExample ce = new ChatExample(); | |
new T1(ce); | |
new T2(ce); | |
} | |
} |
Conclusion:
As we have seen the
importance of thread in java programming. Java threads come handy when we have
a multi-threaded environment. Helps to run the multiple processes at the
background.
Please feel free to add some points and also correct me if I am wrong at any point.
0 Comments