Chapter 2 - Unit 3
Chapter 2 - Unit 3
Chapter 2 - Unit 3
Multithreading
The Java Thread model, thread life cycle, Thread class, Runnable
interface, creating multiple threads, Synchronization, Inter Thread
Communication, Deadlock.
The java programming language allows us to create a program that contains one or
more parts that can run simultaneously at the same time. This type of program is
known as a multithreading program. Each part of this program is called a thread. Every
thread defines a separate path of execution 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
o 1) It doesn't block the user because threads are independent and you can
perform multiple operations at the same time.
o 2) You can perform many operations together, so it saves time.
o 3) Threads are independent, so it doesn't affect other threads if an exception
occurs in a single thread.
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.
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.
Thread life cycle
Thread Life Cycle in Java tells the various information of thread form
born to terminate.
Thread life cycle contains the several stages and at a time any thread
can be present in a single state.
1. Born
2. Ready
3. Running
4. Blocked
5. Sleep
6. Wait
7. Dead
Thread class
Java provides a thread class that has various method calls in order to
manage the behavior of threads by providing constructors and methods to
perform operations on threads.
Ways of creating threads
o Creating own class which is extending to parent Thread class.
o Implementing the Runnable interface.
NewThread()
super("Demo Thread");
try
{
System.out.println("Child Thread: " + i);
Thread.sleep(500);
catch (InterruptedException e)
System.out.println("Child interrupted.");
class ExtendThread
try
Thread.sleep(1000);
catch (InterruptedException e)
}
}
Note :
This program generates the same output as the preceding version.
As you can see, the child thread is created by instantiating an object of
NewThread, which is derived from Thread.
Notice the call to super( ) inside NewThread.
This invokes the following form of the Thread constructor:
public Thread(String threadName)
Here, threadName specifies the name of the thread.
Creating Multiple Threads
Threads So far, you have been using only two threads: the main thread and
one child thread.
However, your program can spawn as many threads as it needs.
For example, the following program creates three child threads:
Thread t;
NewThread(String threadname)
name = threadname;
try {
{
System.out.println(name + ": " + i);
Thread.sleep(1000);
catch (InterruptedException e)
System.out.println(name + "Interrupted");
class MultiThreadDemo
//new NewThread("Three");
try
Thread.sleep(10000);
catch (InterruptedException e)
}
}
isAlive() method
Syntax
public final boolean isAlive()
join() method
Syntax
You can obtain the current priority setting by calling the getPriority( )
method of Thread, shown here:
final int getPriority( )
Synchronization
TestSynchronization1.java
class Table
{
void printTable(int n)
{
//method not synchronized
for(int i=1;i<=5;i++)
{
System.out.println(n*i);
Try
{
Thread.sleep(400);
}
catch(Exception e)
{
System.out.println(e);
}
}
}
}
class MyThread1 extends Thread
{
Table t;
MyThread1(Table t)
{
this.t=t;
}
public void run()
{
t.printTable(5);
}
}
class MyThread2 extends Thread
{
Table t;
MyThread2(Table t)
{
this.t=t;
}
public void run()
{
t.printTable(100);
}
}
class TestSynchronization1
{
public static void main(String args[])
{
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
Suppose we have 50 lines of code in our method, but we want to synchronize only
5 lines, in such cases, we can use synchronized block.
If we put all the codes of the method in the synchronized block, it will work same
as the synchronized method.
Points to Remember
Syntax
class TestSynchronizedBlock1
{
public static void main(String args[])
{
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
Example
class Customer
{
int amount=10000;
synchronized void withdraw(int amount)
{
System.out.println("going to withdraw...");
if(this.amount<amount)
{
System.out.println("Less balance; waiting for deposit...");
System.out.println("Before deposite - current balance:"+this.amount);
try
{
wait();
}
catch(Exception e)
{
}
}
this.amount-=amount;
System.out.println("withdraw completed...");
System.out.println("After withdraw - current balance:"+this.amount);
}
synchronized void deposit(int amount)
{
System.out.println("going to deposit...");
this.amount+=amount;
System.out.println("deposit completed... ");
System.out.println("After deposite - current balance:"+this.amount);
notify();
}
}
class Test
{
public static void main(String args[])
{
final Customer c=new Customer();
new Thread()
{
public void run()
{
c.withdraw(15000);
}
}.start();
new Thread()
{
public void run()
{
c.deposit(10000);
}
}.start();
}
}
Deadlock
Deadlock in Java is a part of multithreading.
Deadlock can occur in a situation when a thread1 is waiting for an object
lock, that is acquired by thread2 and thread2 is waiting for an object lock
that is acquired by thread1.
Since, both threads are waiting for each other to release the lock, the
condition is called deadlock.
Synchronized keyword is used to make the class or method thread-safe
which means only one thread can have lock of synchronized method and
use it, other threads have to wait till the lock releases and anyone of them
acquire that lock.
It is important to use if our program is running in multi-threaded
environment where two or more threads execute simultaneously. But
sometimes it also causes a problem which is called Deadlock.
Below is a simple example of Deadlock condition.
class TestDeadlockExample1
{
public static void main(String[] args)
{
final String resource1 = "RVR";
final String resource2 = "CSE";
// t1 tries to lock resource1 then resource2
Thread t1 = new Thread()
{
public void run()
{
synchronized (resource1)
{
System.out.println("Thread 1: locked resource 1");
try { Thread.sleep(100);} catch (Exception e)
{
}
synchronized (resource2)
{
System.out.println("Thread 1: locked resource 2");
}
}
}
};
// Thread-1
Runnable b1 = new Runnable()
{
public void run()
{
synchronized (b)
{
try
{
/* Adding delay so that both threads can start trying to lock resources */
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
// Thread-1 have resource1 but need resource2 also
synchronized (a)
{
System.out.println("In block 1");
}
}
}
};
// Thread-2
Runnable b2 = new Runnable()
{
public void run()
{
synchronized (b)
{
// Thread-2 have resource2 but need resource1 also
synchronized (a)
{
System.out.println("In block 2");
}
}
}
};
new Thread(b1).start();
new Thread(b2).start();
}
// resource1
private class resource1
{
private int i = 10;
public int getI()
{
return i;
}