Multithreading in Java
Multithreading in Java
Multitasking
Multitasking is a process of executing multiple tasks simultaneously. We use multitasking to utilize the CPU. Multitasking can be achieved in two
ways:
o Process-based Multitasking (Multiprocessing)
o Thread-based Multitasking (Multithreading)
1) Process-based Multitasking (Multiprocessing)
o Each process has an address in memory. In other words, each process allocates a separate memory area.
o A process is heavyweight.
o Cost of communication between the process is high.
o Switching from one process to another requires some time for saving and loading registers, memory maps, updating lists, etc.
2) Thread-based Multitasking (Multithreading)
o Threads share the same address space.
o A thread is lightweight.
o Cost of communication between the thread is low.
Note: At least one process is required for each thread.
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.
Explanation: Whenever we spawn a new thread, that thread attains the new state. When the method start() is invoked on a thread, the thread
scheduler moves that thread to the runnable state. Whenever the join() method is invoked on any thread instance, the current thread executing that
statement has to wait for this thread to finish its execution, i.e., move that thread to the terminated state. Therefore, before the final print statement
is printed on the console, the program invokes the method join() on thread t2, making the thread t1 wait while the thread t2 finishes its execution
and thus, the thread t2 get to the terminated or dead state. Thread t1 goes to the waiting state because it is waiting for thread t2 to finish it's
execution as it has invoked the method join() on thread t2.
How to create a thread in Java
There are two ways to create a thread:
1. By extending Thread class
2. 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:
o Thread()
o Thread(String name)
o Thread(Runnable r)
o Thread(Runnable r,String name)
Commonly used methods of Thread class:
1. public void run(): is used to perform action for a thread.
2. public void start(): starts the execution of the thread.JVM calls the run() method on the thread.
3. public void sleep(long miliseconds): Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of
milliseconds.
4. public void join(): waits for a thread to die.
5. public void join(long miliseconds): waits for a thread to die for the specified miliseconds.
6. public int getPriority(): returns the priority of the thread.
7. public int setPriority(int priority): changes the priority of the thread.
8. public String getName(): returns the name of the thread.
9. public void setName(String name): changes the name of the thread.
10. public Thread currentThread(): returns the reference of currently executing thread.
11. public int getId(): returns the id of the thread.
12. public Thread.State getState(): returns the state of the thread.
13. public boolean isAlive(): tests if the thread is alive.
14. public void yield(): causes the currently executing thread object to temporarily pause and allow other threads to execute.
15. public void suspend(): is used to suspend the thread(depricated).
16. public void resume(): is used to resume the suspended thread(depricated).
17. public void stop(): is used to stop the thread(depricated).
18. public boolean isDaemon(): tests if the thread is a daemon thread.
19. public void setDaemon(boolean b): marks the thread as daemon or user thread.
20. public void interrupt(): interrupts the thread.
21. public boolean isInterrupted(): tests if the thread has been interrupted.
22. public static boolean interrupted(): tests if the current thread has been interrupted.
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().
1. 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:
o A new thread starts(with new callstack).
o The thread moves from New state to the Runnable state.
o When the thread gets a chance to execute, its target run() method will run.
1) Java Thread Example by extending Thread class
FileName: Multi.java
1. class Multi extends Thread{
2. public void run(){
3. System.out.println("thread is running...");
4. }
5. public static void main(String args[]){
6. Multi t1=new Multi();
7. t1.start();
8. }
9. }
Output:
thread is running...
thread is running...
If you are not extending the Thread class, your class object would not be treated as a thread object. So you need to explicitly create the Thread
class object. We are passing the object of your class 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.
FileName: MyThread1.java
1. public class MyThread1
2. {
3. // Main method
4. public static void main(String argvs[])
5. {
6. // creating an object of the Thread class using the constructor Thread(String name)
7. Thread t= new Thread("My first thread");
8.
9. // the start() method moves the thread to the active state
10. t.start();
11. // getting the thread name by invoking the getName() method
12. String str = t.getName();
13. System.out.println(str);
14. }
15. }
Output:
My first thread
My new thread
Now the thread is running ...
Multithreading is a Java feature that allows concurrent execution of two or more parts of a program for maximum
utilization of CPU. Each part of such program is called a thread. So, threads are light-weight processes within a process.
Threads can be created by using two mechanisms :
1. Extending the Thread class
2. Implementing the Runnable Interface
Thread creation by extending the Thread class
We create a class that extends the java.lang.Thread class. This class overrides the run() method available in the Thread
class. A thread begins its life inside run() method. We create an object of our new class and call start() method to start the
execution of a thread. Start() invokes the run() method on the Thread object.
/ Java code for thread creation by extending
// the Thread class
class MultithreadingDemo extends Thread {
public void run()
{
try {
// Displaying the thread that is running
System.out.println(
"Thread " + Thread.currentThread().getId()
+ " is running");
}
catch (Exception e) {
// Throwing an exception
System.out.println("Exception is caught");
}
}
}
// Main Class
public class Multithread {
public static void main(String[] args)
{
int n = 8; // Number of threads
for (int i = 0; i < n; i++) {
MultithreadingDemo object
= new MultithreadingDemo();
object.start();
}
}
}
Output
Thread 15 is running
Thread 14 is running
Thread 16 is running
Thread 12 is running
Thread 11 is running
Thread 13 is running
Thread 18 is running
Thread 17 is running
Thread creation by implementing the Runnable Interface
We create a new class which implements java.lang.Runnable interface and override run() method. Then we instantiate a
Thread object and call start() method on this object.
Java
// Java code for thread creation by implementing
// the Runnable Interface
class MultithreadingDemo implements Runnable {
public void run()
{
try {
// Displaying the thread that is running
System.out.println(
"Thread " + Thread.currentThread().getId()
+ " is running");
}
catch (Exception e) {
// Throwing an exception
System.out.println("Exception is caught");
}
}
}
// Main Class
class Multithread {
public static void main(String[] args)
{
int n = 8; // Number of threads
for (int i = 0; i < n; i++) {
Thread object
= new Thread(new MultithreadingDemo());
object.start();
}
}
}
Output
Thread 13 is running
Thread 11 is running
Thread 12 is running
Thread 15 is running
Thread 14 is running
Thread 18 is running
Thread 17 is running
Thread 16 is running
Thread Class vs Runnable Interface
1. If we extend the Thread class, our class cannot extend any other class because Java doesn’t support multiple
inheritance. But, if we implement the Runnable interface, our class can still extend other base classes.
2. We can achieve basic functionality of a thread by extending Thread class because it provides some inbuilt methods
like yield(), interrupt() etc. that are not available in Runnable interface.
3. Using runnable will give you an object that can be shared amongst multiple threads.
A thread in Java at any point of time exists in any one of the following states. A thread lies only in one of the shown states
at any instant:
1. New State
2. Runnable State
3. Blocked State
4. Waiting State
5. Timed Waiting State
6. Terminated State
The diagram shown below represents various states of a thread at any instant in time.
Because it exits normally. This happens when the code of the thread has been entirely executed by the program.
Because there occurred some unusual erroneous event, like a segmentation fault or an unhandled exception.
Implementing the Thread States in Java
In Java, to get the current state of the thread, use Thread.getState() method to get the current state of the thread. Java
provides java.lang.Thread.State class that defines the ENUM constants for the state of a thread, as a summary of which
is given below:
1. New
Thread state for a thread that has not yet started.
public static final Thread.State NEW
2. Runnable
Thread state for a runnable thread. A thread in the runnable state is executing in the Java virtual machine but it may be
waiting for other resources from the operating system such as a processor.
public static final Thread.State RUNNABLE
3. Blocked
Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to
enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait().
public static final Thread.State BLOCKED
4. Waiting
Thread state for a waiting thread. A thread is in the waiting state due to calling one of the following methods:
Object.wait with no timeout
Thread.join with no timeout
LockSupport.park
public static final Thread.State WAITING
5. Timed Waiting
Thread state for a waiting thread with a specified waiting time. A thread is in the timed waiting state due to calling one of
the following methods with a specified positive waiting time:
Thread.sleep
Object.wait with timeout
Thread.join with timeout
LockSupport.parkNanos
LockSupport.parkUntil
public static final Thread.State TIMED_WAITING
6. Terminated
Thread state for a terminated thread. The thread has completed execution.
Declaration: public static final Thread.State TERMINATED
Example
Below is the implementation of the thread states mentioned above:
1
// Java program to demonstrate thread states
2
class thread implements Runnable {
3
public void run()
4
{
5
// moving thread2 to timed waiting state
6
try {
7
Thread.sleep(1500);
8
}
9
catch (InterruptedException e) {
10
e.printStackTrace();
11
}
12
13
System.out.println(
14
"State of thread1 while it called join() method on thread2 -"
15
+ Test.thread1.getState());
16
try {
17
Thread.sleep(200);
18
}
19
catch (InterruptedException e) {
20
e.printStackTrace();
21
}
22
}
23
}
24
25
public class Test implements Runnable {
26
public static Thread thread1;
27
public static Test obj;
28
29
public static void main(String[] args)
30
{
31
obj = new Test();
32
thread1 = new Thread(obj);
33
34
// thread1 created and is currently in the NEW
35
// state.
36
System.out.println(
37
"State of thread1 after creating it - "
38
+ thread1.getState());
39
thread1.start();
40
41
// thread1 moved to Runnable state
42
System.out.println(
43
"State of thread1 after calling .start() method on it - "
44
+ thread1.getState());
45
}
46
47
public void run()
48
{
49
thread myThread = new thread();
50
Thread thread2 = new Thread(myThread);
51
52
// thread2 created and is currently in the NEW
53
// state.
54
System.out.println(
55
"State of thread2 after creating it - "
56
+ thread2.getState());
57
thread2.start();
58
59
// thread2 moved to Runnable state
60
System.out.println(
61
"State of thread2 after calling .start() method on it - "
62
+ thread2.getState());
63
64
// moving thread2 to timed waiting state
65
try {
66
// moving thread2 to timed waiting state
67
Thread.sleep(200);
68
}
69
catch (InterruptedException e) {
70
e.printStackTrace();
71
}
72
System.out.println(
73
"State of thread2 after calling .sleep() method on it - "
74
+ thread2.getState());
75
76
try {
77
// waiting for thread2 to die
78
thread2.join();
79
}
80
catch (InterruptedException e) {
81
e.printStackTrace();
82
}
83
System.out.println(
84
"State of thread2 when it has finished it's execution - "
85
+ thread2.getState());
86
}
87
}
Output
State of thread1 after creating it - NEW
State of thread1 after calling .start() method on it - RUNNABLE
State of thread2 after creating it - NEW
State of thread2 after calling .start() method on it - RUNNABLE
State of thread2 after calling .sleep() method on it - TIMED_WAITING
State of thread1 while it called join() method on thread2 -WAITING
State of thread2 when it has finished it's execution - TERMINATED
Explanation of the above Program
When a new thread is created, the thread is in the NEW state. When the start() method is called on a thread, the thread
scheduler moves it to the Runnable state. Whenever the join() method is called on a thread instance, the current thread
executing that statement will wait for this thread to move to the Terminated state. So, before the final statement is printed
on the console, the program calls join() on thread2 making the thread1 wait while thread2 completes its execution and is
moved to the Terminated state. thread1 goes to the Waiting state because it is waiting for thread2 to complete its
execution as it has called join on thread2.
Java Thread Priority in Multithreading
Whenever we create a thread in Java, it always has some priority assigned to it. Priority can either be given by JVM while
creating the thread or it can be given by the programmer explicitly.
Priorities in threads is a concept where each thread is having a priority which in layman’s language one can say every
object is having priority here which is represented by numbers ranging from 1 to 10.
The default priority is set to 5 as excepted.
Minimum priority is set to 1.
Maximum priority is set to 10.
Here 3 constants are defined in it namely as follows:
1. public static int NORM_PRIORITY
2. public static int MIN_PRIORITY
3. public static int MAX_PRIORITY
Let us discuss it with an example to get how internally the work is getting executed. Here we will be using the knowledge
gathered above as follows:
We will use currentThread() method to get the name of the current thread. User can also use setName() method if
he/she wants to make names of thread as per choice for understanding purposes.
getName() method will be used to get the name of the thread.
The accepted value of priority for a thread is in the range of 1 to 10.
Let us do discuss how to get and set priority of a thread in java.
1. public final int getPriority(): java.lang.Thread.getPriority() method returns priority of given thread.
2. public final void setPriority(int newPriority): java.lang.Thread.setPriority() method changes the priority of thread to
the value newPriority. This method throws IllegalArgumentException if value of parameter newPriority goes beyond
minimum(1) and maximum(10) limit.
Example
Java
import java.lang.*;
// Main class
// Method 1
{ // Print statement
}
// Main driver method
// Thread 1
// Thread 3
t1.setPriority(2);
t2.setPriority(5);
t3.setPriority(8);
// 2
// 5
// 8
Thread.currentThread().setPriority(10);
+ Thread.currentThread().getPriority());
Output
t1 thread priority : 5
t2 thread priority : 5
t3 thread priority : 5
t1 thread priority : 2
t2 thread priority : 5
t3 thread priority : 8
Currently Executing Thread : main
Main thread priority : 5
Main thread priority : 10
Output explanation:
Thread with the highest priority will get an execution chance prior to other threads. Suppose there are 3 threads t1, t2,
and t3 with priorities 4, 6, and 1. So, thread t2 will execute first based on maximum priority 6 after that t1 will execute
and then t3.
The default priority for the main thread is always 5, it can be changed later. The default priority for all other threads
depends on the priority of the parent thread.
Now geeks you must be wondering out what if we do assign the same priorities to threads then what will happen. All the
processing in order to look after threads is carried with help of the thread scheduler. One can refer to the below example
of what will happen if the priorities are set to the same and later onwards we will discuss it as an output explanation to
have a better understanding conceptually and practically.
Example
Java
import java.lang.*;
// Main class
// ThreadDemo
// Method 1
{ // Print statement
// Method 2
Thread.currentThread().setPriority(6);
System.out.println(
+ Thread.currentThread().getPriority());
// main()
} }
Output
A. Runnable
B. Thread
C. Executor
D. ThreadPool
A. run()
B. begin()
C. start()
D. execute()
A. run()
B. start()
C. execute()
D. begin()
A. java.util
B. java.thread
C. java.lang
D. java.concurrent
A. 0
B. 1
C. 5
D. 10
7. Which method is used to pause a thread for a specific time?
A. wait()
B. sleep()
C. pause()
D. halt()
A. Runs successfully
B. Throws IllegalThreadStateException
C. Creates a new thread
D. Restarts the thread
A. Using stop()
B. Using interrupt()
C. Using sleep()
D. Threads cannot be stopped
A. run()
B. start()
C. call()
D. execute()
A. Kernel-level threads
B. User-level threads
C. Both kernel and user-level threads
D. Hybrid threads
A. Using setPriority()
B. Using setDaemon(true)
C. Using startDaemon()
D. By creating it in the main thread
A. isAlive()
B. checkStatus()
C. isRunning()
D. threadState()
A. synchronized
B. static
C. volatile
D. thread-safe
A. ThreadGroup
B. Thread
C. Executor
D. Future
A. Stops a thread
B. Waits for a thread to start
C. Causes a thread to wait until notified
D. Suspends a thread
A. notifyAll()
B. notify()
C. start()
D. Both A and B
A. Blocked
B. Waiting
C. Runnable
D. Terminated
A. checkInterrupt()
B. isInterrupted()
C. threadInterrupted()
D. interrupted()
A. Ready
B. Waiting
C. Terminated
D. All of the above
25. How many threads can be run at a time in Java?
A. One
B. Two
C. Depends on CPU
D. Unlimited
A. setThreadPriority()
B. setPriority()
C. prioritizeThread()
D. setPriorityLevel()
A. Yes
B. No
C. Only if it’s a daemon thread
D. Only if set as runnable
1. A thread in Java can be created by extending the ______ class or implementing the ______ interface.
Answer: Thread, Runnable
2. The ______ method is used to start the execution of a thread.
Answer: start()
3. The keyword ______ is used to ensure that a block of code is accessed by only one thread at a time.
Answer: synchronized
4. A thread that runs in the background and performs tasks such as garbage collection is called a
______ thread.
Answer: daemon
5. The ______ method causes the current thread to temporarily pause its execution and allow other
threads to execute.
Answer: yield()
6. The ______ method is used to make a thread wait until it is notified.
Answer: wait()
7. The default priority of a thread in Java is ______.
Answer: 5
8. The ______ method is used to check if a thread is alive.
Answer: isAlive()
9. The ______ class in the java.util.concurrent package is used to create thread pools.
Answer: Executor
10. The ______ method in Java interrupts a thread that is currently sleeping or waiting.
Answer: interrupt()
Match-the-following activity :-
Answers
1. start() → C
2. run() → J
3. synchronized → D
4. Daemon thread → E
5. Executor → I
6. join() → F
7. isAlive() → B
8. yield() → G
9. wait() → A
10. interrupt() → H