Unit - 4
Multithreading in Java
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 area so saves
memory, and context-switching between the threads takes less time than
process.
Java Multithreading is mostly used in games, animation, etc.
Advantages of Java Multithreading
1) It doesn't block the user because threads are independent and you can
perform multiple operations at the same time.
2) You can perform many operations together, so it saves time.
3) Threads are independent, so it doesn't affect other threads if an
exception occurs in a single thread.
What is Thread in java
A thread is a lightweight sub process, 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.
S.N. Modifier and Type Method Description
1) void start() It is used to
start the
execution of
the thread.
2) void run() It is used to
do an action
for a thread.
3) static void sleep() It sleeps a
thread for
the
specified
amount of
time.
4) static Thread currentThread() It returns a
reference to
the
currently
executing
thread
object.
5) void join() It waits for a
thread to
die.
6) int getPriority() It returns
the priority
of the
thread.
7) void setPriority() It changes
the priority
of the
thread.
8) String getName() It returns
the name of
the thread.
9) void setName() It changes
the name of
the thread.
10) long getId() It returns
the id of the
thread.
As shown in the above figure, a thread is executed inside the process. There
is context-switching between the threads. There can be multiple processes
inside the OS, and one process can have multiple threads.
Java Thread Methods
Life cycle of a Thread (Thread States)
In Java, a thread always exists in any one of the following states. These
states are:
1. New
2. Active
3. Blocked / Waiting
4. Timed Waiting
5. Terminated
Explanation of Different Thread States
New: Whenever a new thread is created, it is always in the new state. For a
thread in the new state, the code has not been run yet and thus has not
begun its execution.
Active: When a thread invokes the start() method, it moves from the new
state to the active state. The active state contains two states within it: one
is runnable, and the other is running.
o Runnable: A thread, that is ready to run is then moved to the runnable
state. In the runnable state, the thread may be running or may be ready to
run at any given instant of time. It is the duty of the thread scheduler to
provide the thread time to run, i.e., moving the thread the running state.
o Running: When the thread gets the CPU, it moves from the runnable
to the running state. Generally, the most common change in the state
of a thread is from runnable to running and again back to runnable.
Blocked or Waiting: Whenever a thread is inactive for a span of time (not
permanently) then, either the thread is in the blocked state or is in the waiting
state.
Timed Waiting: Sometimes, waiting for leads to starvation. For example, a
thread (its name is A) has entered the critical section of a code and is not
willing to leave that critical section. In such a scenario, another thread (its
name is B) has to wait forever, which leads to starvation. To avoid such
scenario, a timed waiting state is given to thread B. Thus, thread lies in the
waiting state for a specific span of time, and not forever. A real example of
timed waiting is when we invoke the sleep() method on a specific thread. The
sleep() method puts the thread in the timed wait state. After the time runs
out, the thread wakes up and start its execution from when it has left earlier.
Terminated: A thread reaches the termination state because of the
following reasons:
o When a thread has finished its job, then it exists or terminates
normally.
o Abnormal termination: It occurs when some unusual events such as
an unhandled exception or segmentation fault.
A terminated thread means the thread is no more in the system. In other
words, the thread is dead, and there is no way one can respawn (active after
kill) the dead thread.
Java Threads | 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)
1.Java Thread Example by extending Thread class
File Name: Multi.java
1. class Multi extends Thread {
2. public void run ()
3. {
4. System.out.println("thread is running...");
5. }
6. public static void main (String args []){
7. Multi t1=new Multi ();
8. t1.start ();
9. }
10.}
Output:
thread is running...
2.Java Thread Example by implementing Runnable interface
File Name: Multi3.java
1. class Multi3 implements Runnable
2. {
3. public void run ()
4. {
5. System.out.println("thread is running...");
6. }
7. public static void main (String args[]){
8. Multi3 m1=new Multi3();
9. Thread t1 =new Thread(m1); // Using the constructor Thread(Runnable r)
10.t1.start ();
11. }
12.}
Output:
thread is running...
3)Using the Thread Class: Thread (String Name)
We can directly use the Thread class to spawn new threads using the
constructors defined above.
File Name: 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
4) Using the Thread Class: Thread (Runnable r, String name)
Observe the following program.
File Name: MyThread2.java
1. public class MyThread2 implements Runnable
2. {
3. public void run()
4. {
5. System.out.println("Now the thread is running ...");
6. }
7.
8. // main method
9. public static void main (String argvs [])
10.{
11.// creating an object of the class MyThread2
12.Runnable r1 = new MyThread2();
13.
14.// creating an object of the class Thread using Thread(Runnable r, String name)
15.Thread th1 = new Thread(r1, "My new thread");
16.
17.// the start() method moves the thread to the active state
18.th1.start();
19.
20.// getting the thread name by invoking the getName() method
21.String str = th1.getName();
22.System.out.println(str);
23.}
24.}
Output:
My new thread
Now the thread is running ...
Thread Synchronization in Java
Synchronization in Java is the capability to control the access of multiple
threads to any shared resource.
Java Synchronization is better option where we want to allow only one thread
to access the shared resource.
Why use Synchronization?
The synchronization is mainly used to
1. To prevent thread interference.
2. To prevent consistency problem.
Types of Synchronization
There are two types of synchronization
1. Process Synchronization
2. Thread Synchronization
Thread Synchronization
There are two types of thread synchronization mutual exclusive and inter-
thread communication.
1. Mutual Exclusive
1. Synchronized method.
2. Synchronized block.
3. Static synchronization.
2. Cooperation (Inter-thread communication in java)
Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another while
sharing data. It can be achieved by using the following three ways:
1. By Using Synchronized Method
2. By Using Synchronized Block
3. By Using Static Synchronization
Concept of Lock in Java
Synchronization is built around an internal entity known as the lock or
monitor. Every object has a lock associated with it. By convention, a thread
that needs consistent access to an object's fields has to acquire the object's
lock before accessing them, and then release the lock when it's done with
them.
From Java 5 the package java.util. concurrent.locks contains several lock
implementations.
Understanding the problem without
Synchronization
In this example, there is no synchronization, so output is inconsistent. Let's
see the example:
TestSynchronization1.java
1. class Table{
2. void printTable(int n){//method not synchronized
3. for(int i=1;i<=5;i++){
4. System.out.println(n*i);
5. try{
6. Thread.sleep(400);
7. }catch(Exception e){System.out.println(e);}
8. }
9.
10. }
11.}
12.
13.class MyThread1 extends Thread{
14.Table t;
15.MyThread1(Table t){
16.this.t=t;
17.}
18.public void run(){
19.t.printTable(5);
20.}
21.
22.}
23.class MyThread2 extends Thread{
24.Table t;
25.MyThread2(Table t){
26.this.t=t;
27.}
28.public void run(){
29.t.printTable(100);
30.}
31.}
32.
33.class TestSynchronization1{
34.public static void main(String args[]){
35.Table obj = new Table();//only one object
36.MyThread1 t1=new MyThread1(obj);
37.MyThread2 t2=new MyThread2(obj);
38.t1.start();
39.t2.start();
40.}
41.}
Output:
5
100
10
200
15
300
20
400
25
500
Java Synchronized Method
If you declare any method as synchronized, it is known as synchronized
method.
Synchronized method is used to lock an object for any shared resource.
When a thread invokes a synchronized method, it automatically acquires the
lock for that object and releases it when the thread completes its task.
TestSynchronization2.java
1. //example of java synchronized method
2. class Table{
3. synchronized void printTable(int n){//synchronized method
4. for(int i=1;i<=5;i++){
5. System.out.println(n*i);
6. try{
7. Thread.sleep(400);
8. }catch(Exception e){System.out.println(e);}
9. }
10.
11. }
12.}
13.
14.class MyThread1 extends Thread{
15.Table t;
16.MyThread1(Table t){
17.this.t=t;
18.}
19.public void run(){
20.t.printTable(5);
21.}
22.
23.}
24.class MyThread2 extends Thread{
25.Table t;
26.MyThread2(Table t){
27.this.t=t;
28.}
29.public void run(){
30.t.printTable(100);
31.}
32.}
33.
34.public class TestSynchronization2{
35.public static void main(String args[]){
36.Table obj = new Table();//only one object
37.MyThread1 t1=new MyThread1(obj);
38.MyThread2 t2=new MyThread2(obj);
39.t1.start();
40.t2.start();
41.}
42.}
Output:
5
10
15
20
25
100
200
300
400
500
Example of synchronized method by using
annonymous class
In this program, we have created the two threads by using the anonymous
class, so less coding is required.
TestSynchronization3.java
1. //Program of synchronized method by using annonymous class
2. class Table{
3. synchronized void printTable(int n){//synchronized method
4. for(int i=1;i<=5;i++){
5. System.out.println(n*i);
6. try{
7. Thread.sleep(400);
8. }catch(Exception e){System.out.println(e);}
9. }
10.
11. }
12.}
13.
14.public class TestSynchronization3{
15.public static void main(String args[]){
16.final Table obj = new Table();//only one object
17.
18.Thread t1=new Thread(){
19.public void run(){
20.obj.printTable(5);
21.}
22.};
23.Thread t2=new Thread(){
24.public void run(){
25.obj.printTable(100);
26.}
27.};
28.
29.t1.start();
30.t2.start();
31.}
32.}
Output:
5
10
15
20
25
100
200
300
400
500
5
100
10
200
15
300
20
400
25
500
5
100
10
200
15
300
20
400
25
500