0% found this document useful (0 votes)
35 views33 pages

3 - Multithreading (Unit-2)

The document provides an overview of threads and multithreading in Java, explaining their characteristics, advantages, and lifecycle states. It details how to create threads using the Thread class and Runnable interface, along with common methods like start(), join(), and sleep(). Additionally, it covers thread priorities, daemon threads, and garbage collection, emphasizing the importance of efficient memory management in Java applications.

Uploaded by

rajatmaurya7906
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
35 views33 pages

3 - Multithreading (Unit-2)

The document provides an overview of threads and multithreading in Java, explaining their characteristics, advantages, and lifecycle states. It details how to create threads using the Thread class and Runnable interface, along with common methods like start(), join(), and sleep(). Additionally, it covers thread priorities, daemon threads, and garbage collection, emphasizing the importance of efficient memory management in Java applications.

Uploaded by

rajatmaurya7906
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 33

Thread

• A single program can perform multiple task dispatching


multiple threads for them.

• A thread is smallest unit of code that can be dispatched


by thread scheduler.

• How ever only single thread will be executed at a given


point of time.
For example: Multi-Player gaming.
Threads allows a program to operate more efficiently by
doing multiple things at the same time.
• Referred as lightweight process
• A thread is a series of executed statements
• Each thread has its own program counter, stack and local
variables
• A thread is a nested sequence of method calls
• Its shares memory, files and per-process state

- Threads can be used to perform complicated tasks in the


background without interrupting the main program.
Multithreading
• It is a process of executing multiple threads simultaneously.
• Thread is a lightweight sub-process, a smallest unit of processing.
• Multiprocessing & multithreading, are used to achieve multitasking.
• But we use multithreading as threads share a common memory
area.
- They don't allocate separate memory area so saves memory, and
context-switching between the threads takes less time than
process.
Advantages of Multithreading

1) Increases CPU utilization i.e., CPU is made busy


(always executing some thread) without leaving it
idle.

2) Doesn't block the user because threads are


independent and we can perform multiple
operations at same time, thus saves time.
Life cycle of a Thread (Thread States)

A thread can be
in one of the five
states.
Life cycle of the thread
is controlled by JVM.
The java thread states are as follows:
1. New : Thread begins its life cycle and remains in this state until
the start() method is called on it.
2. Runnable : reach after invocation of start() method on new
thread, 3. Running : reach in this state if the thread scheduler has
selected it.
4. Waiting : Thread waits for another thread to perform a task and is
still alive.
5. Terminated : A thread enter this state when it complete its task.
How to create thread:
There are two ways to create a thread:

1. extending Thread class 2. implementing Runnable


interface.

(A) 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 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 currently executing thread to sleep (temporarily cease
execution) for specified no of millisecs.
4. public void join(): waits for a thread to die.
5. public int getPriority(): returns the priority of the thread.
6. public int setPriority(int priority): changes the priority of the thread.
7. public String getName(): returns the name of the thread.
8. public void setName(String name): changes the name of the thread.
9. public Thread currentThread(): returns the reference of currently executing thread.
10. public int getId(): returns the id of the thread.
11. public boolean isAlive(): tests if the thread is alive.
12. public void yield(): causes currently executing thread object to temporarily pause & allow other threads
to execute.
13. public void suspend(): is used to suspend the thread(depricated).
14. public void resume(): is used to resume the suspended thread(depricated).
15. public void stop(): is used to stop the thread(depricated).
16. public boolean isDaemon(): tests if the thread is a daemon thread.
17. public void setDaemon(boolean b): marks the thread as daemon or user thread.
(B) 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().
public void run(): is used to perform action for a thread.
Starting a thread:
• start() method of Thread class is used to start a newly created
thread.
• It performs following tasks:
• A new thread starts(with new callstack).
• The thread moves from New state to the Runnable state.
• When the thread gets a chance to execute, its target run()
method will run.
class Multi extends Thread {
Thread public void run()
Example by { System.out.println("thread is running...");
extending } Output: thread is
Thread public static void main(String args[]) { running...
class Multi t1=new Multi();
t1.start();
}}

class Multi implements Runnable


{ public void run() { System.out.println("thread is running...");
} Output:
Thread Example public static void main(String args[]) thread is
running...
by implementing { Multi m1=new Multi();
Runnable Thread t1 =new Thread(m1);
interface t1.start();
}}
Thread Scheduler
• It is the part of the JVM that decides which thread should
run.

• There is no guarantee that which runnable thread will be


chosen to run by the thread scheduler.

• Only one thread at a time can run in a single process.


Sleep() method
used to sleep a thread for the specified amount of time.
class TestSleepMethod1 extends Thread{
public void run(){
for(int i=1;i<5;i++){
try{ Output:
Thread.sleep(500); 1
}catch(InterruptedException e){System.out.println(e);}
1
System.out.println(i);
} } 2
public static void main(String args[]){ 2
TestSleepMethod1 t1=new TestSleepMethod1(); 3
TestSleepMethod1 t2=new TestSleepMethod1(); 3
4
t1.start(); 4
t2.start();
} }

at a time only one thread is executed. If you sleep a thread for the specified time, the thread scheduler picks up another
thread and so on.
Can we start a Thread twice in Java?
• Once a thread is started, it can never be started again.
• Doing so will throw an IllegalThreadStateException.
public class TestThreadTwice1 extends Thread{
public void run(){
System.out.println("running...");
}
public static void main(String args[]){
TestThreadTwice1 t1=new TestThreadTwice1();
t1.start();
t1.start();
}
}

Output: running
Exception in thread "main" java.lang.IllegalThreadStateException

the first call to start() resulted in execution of run() method, however the exception got thrown when
we tried to call the start() second time.
The join() method
• The join() method waits for a thread to die.
• Causes the currently running threads to stop executing until the thread it joins with completes its task.

class TestJoinMethod1 extends Thread{


public void run(){
Output:
for(int i=1;i<=5;i++){
1
try{ 2
Thread.sleep(500); 3
Example : }catch(Exception e){System.out.println(e);} 4
System.out.println(i); } } 5
1 In example, when t1
public static void main(String args[]){
1 completes its task then t2
TestJoinMethod1 t1=new TestJoinMethod1(); and t3 starts executing.
2
TestJoinMethod1 t2=new TestJoinMethod1(); 2
TestJoinMethod1 t3=new TestJoinMethod1(); 3
t1.start(); 3
try{ 4
t1.join(); 4
5
}catch(Exception e){System.out.println(e);}
5

t2.start();
t3.start(); } }
yield() method
The yield() method of thread class causes the currently executing thread object to temporarily pause and allow other threads to
execute.
Syntax: public static void yield()

Example
public class JavaYieldExp extends Thread {
public void run() {
for (int i=0; i<3 ; i++)
Output:
System.out.println(Thread.currentThread().getName() + " in control");
main in control
}
main in control
public static void main(String[]args) {
main in control
JavaYieldExp t1 = new JavaYieldExp();
Thread-0 in control
JavaYieldExp t2 = new JavaYieldExp();
Thread-0 in control
// this will call run() method
Thread-0 in control
t1.start();
Thread-1 in control
t2.start();
Thread-1 in control
for (int i=0; i<3; i++) {
Thread-1 in control
// Control passes to child thread
t1.yield();
System.out.println(Thread.currentThread().getName() + " in control");
} } }
getName(),setName(String) and getId() method:
class TestJoinMethod3 extends Thread{
public void run(){
System.out.println("running..."); } Output:
Name of t1:Thread-0
public static void main(String args[]){ Name of t2:Thread-1
TestJoinMethod3 t1=new TestJoinMethod3(); id of t1:8
TestJoinMethod3 t2=new TestJoinMethod3(); running...
After changling name of t1: MereKrishna
System.out.println("Name of t1:"+t1.getName()); running...
System.out.println("Name of t2:"+t2.getName());
System.out.println("id of t1:"+t1.getId());
t1.start();
t2.start();
t1.setName(“MereKrishna");
System.out.println("After changing name of
t1:"+t1.getName());
} }
The currentThread() method:
returns a reference to the currently executing thread object.

class TestJoinMethod4 extends Thread{


public void run(){
Example : System.out.println(Thread.currentThread().getName());
Output:
} Thread-0
} Thread-1
public static void main(String args[]){
TestJoinMethod4 t1=new TestJoinMethod4();
TestJoinMethod4 t2=new TestJoinMethod4();

t1.start();
t2.start();
}
}
Priority of a Thread (Thread Priority):

• Each thread have a priority.


• Priorities are represented by a number between 1 and 10.
• In most cases, thread schedular schedules the threads according to their priority (known as
preemptive scheduling). But it is not guaranteed because it depends on JVM specification that
which scheduling it chooses.

3 constants defined in Thread class:

1. public static int MIN_PRIORITY


2. public static int NORM_PRIORITY
3. public static int MAX_PRIORITY

• Default priority of a thread is 5 (NORM_PRIORITY).


• The value of MIN_PRIORITY is 1 and
• The value of MAX_PRIORITY is 10.
Thread Constants
We can fetch priority of a thread by using some predefined constants provided by the Thread class.
these constants returns the max, min and normal priority of a thread.

class MyThread extends Thread {


public void run() {
System.out.println("Thread Running...");
}

public static void main(String[]args) {


MyThread p1 = new MyThread();
p1.start();
System.out.println("max thread priority : " +
p1.MAX_PRIORITY); Output:
System.out.println("min thread priority : " + Thread Running...
p1.MIN_PRIORITY); max thread priority : 10
System.out.println("normal thread priority : " + min thread priority : 1
p1.NORM_PRIORITY); normal thread priority : 5
}}
Set Priority
To set priority of a thread, setPriority() method of thread class is used.
It takes an integer argument that must be between 1 and 10. see the below example.

Example :

class TestMultiPriority1 extends Thread {


public void run() {
System.out.println("running thread name is:"+Thread.currentThread().getName());
System.out.println("running thread priority is:"+Thread.currentThread().getPriority());
}
public static void main(String args[]){
TestMultiPriority1 m1=new TestMultiPriority1();
TestMultiPriority1 m2=new TestMultiPriority1();
m1.setPriority(Thread.MIN_PRIORITY);
m2.setPriority(Thread.MAX_PRIORITY);
m1.start();
m2.start(); } }
Daemon thread
• It is a service provider thread, provides services to the user thread for background
supporting tasks.
• Its life depends on user threads.
• When all the user threads dies, JVM terminates this thread automatically.
• It is a low priority thread.
• There are many java daemon threads running automatically e.g. gc, finalizer etc.
All threads created inside main method (child threads of main thread) are non-daemon by
default.
However we can make a user thread to Daemon by using setDaemon() method of thread
class.
setDaemon() method
• setDaemon() method can only be called before starting the thread.
• This method would throw IllegalThreadStateException if this method after
Thread.start() method.
Example:

public class TestDaemonThread1 extends Thread{


public void run(){
if(Thread.currentThread().isDaemon()) { //checking for daemon thread
System.out.println("daemon thread work"); } Output:
else{
daemon thread work
System.out.println("user thread work"); user thread work
} } user thread work
public static void main(String[] args){
TestDaemonThread1 t1=new TestDaemonThread1(); //creating thread object
TestDaemonThread1 t2=new TestDaemonThread1();
TestDaemonThread1 t3=new TestDaemonThread1();
t1.setDaemon(true); //now t1 is daemon thread
t1.start(); //starting threads
t2.start();
t3.start();
} }
ThreadGroup in Java
A convenient way to group multiple threads in a single object.
Allows to suspend, resume or interrupt group of threads by a single method call.

Note: Now suspend(), resume() and stop() methods are deprecated.

Thread group is implemented by java.lang.ThreadGroup class.

Constructors of ThreadGroup class: There are only two constructors of ThreadGroup class:

• ThreadGroup(String name)

• ThreadGroup(ThreadGroup parent, String name)


Main Thread
• When a Java program starts up, one thread begins running immediately.
• This is usually called the main thread of our program, because it is the one that is executed when our
program begins.
• Often, it must be the last thread to finish execution because it performs various shutdown actions
public class Driver {
public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
System.out.println("Current thread: " + mainThread); Output:
Ex: mainThread.setName("My Thread"); Current thread: Thread[main,5,main]
System.out.println("After name change: " + mainThread); After name change: Thread[My Thread,5,main]
try i=1
{ i=2
for(int i = 1; i <= 5; i++) i=3
{ i=4
System.out.println("i = " + i); i=5
Thread.sleep(1000); } }
catch(InterruptedException e) {
System.out.println("Thread is interrupted!"); } } }

Relation between the main() method and main thread :


• For each program, a Main thread is created by JVM(Java Virtual Machine).
• The “Main” thread first verifies the existence of the main() method, and then it initializes the class.
• Note that from JDK 6, main() method is mandatory in a standalone java application.
Garbage Collection
• garbage means unreferenced objects.
• Garbage Collection is process of reclaiming the runtime unused memory
automatically.
• it is a way to destroy the unused objects.
• To do so, we were using free() function in C language and delete() in C++.
• But, in java it is performed automatically. So, java provides better memory
management.

Advantage of Garbage Collection

• It makes java memory efficient because garbage collector


removes the unreferenced objects from heap memory.
• It is automatically done by the garbage collector(a part of JVM)
so we don't need to make extra efforts.
finalize() method
• The finalize() method is invoked each time before the object is garbage collected.
• This method can be used to perform cleanup processing.
• This method is defined in Object class as:
protected void finalize(){}
gc() method
The gc() method is used to invoke the garbage collector to perform cleanup processing.
The gc() is found in System and Runtime classes.
public static void gc(){}
Example of garbage collection:
public class TestGarbage1{
public void finalize(){System.out.println("object is garbage collected");}
public static void main(String args[]){
TestGarbage1 s1=new TestGarbage1();
TestGarbage1 s2=new TestGarbage1(); object is garbage collected
s1=null; object is garbage collected
s2=null;
System.gc();
} }
Synchronization
1. Process of controlling the access of multiple threads to shared resources or critical
sections of code.
2. It ensures that only one thread can access a particular section of code or object at a
time, thereby preventing data corruption and maintaining data consistency in
multithreaded environments.

Types of Synchronization: 1. Process Synchronization 2. Thread Synchronization

Thread synchronization : mutual exclusive & inter-thread communication


(a) Mutual Exclusive
Synchronized method.
Synchronized block.
static synchronization.

(b) Inter-thread communication


wait(), notify(), notifyAll()
synchronized method
• synchronized keyword is used to ensure that:
• only one thread can execute a particular block of code or method at a time.
• It helps in preventing multiple threads from interfering with each other when accessing shared resources.
• Avoid data inconsistencies and race conditions in multithreaded programs.

class MultiplicationTable {
Ex: synchronized static void printTable(int num) { public void run() {
for (int i = 1; i <= 10; i++) { MultiplicationTable.printTable(num);
System.out.println(num + " * " + i + " = " + (num * i)); }
}
try {
Thread.sleep(100); // Adding delay for better visualization public class abc1 {
} catch (InterruptedException e) { public static void main(String[] args) {
System.out.println(e); // Creating two threads to print tables of two different numbers
} TablePrinter thread1 = new TablePrinter(3); // Table of 3
} TablePrinter thread2 = new TablePrinter(7); // Table of 7
System.out.println(); // Empty line for clarity
} } // Starting both threads
class TablePrinter extends Thread { thread1.start();
int num; thread2.start();
} }
TablePrinter(int num) {
this.num = num;
}
Synchronized Block

• Synchronized block can be used to perform synchronization on any


specific resource of the method.

• Suppose among 80 lines of code in a method, if its required to


synchronize only 5 lines, we can use synchronized block.

• If all the codes of the method are put in the synchronized block, it
will work same as the synchronized method.
• Scope of synchronized block is smaller than the method.
Inter-thread Communication or Co-operation
• It is all about allowing synchronized threads to communicate with each other.
• A thread is paused running in its critical section and another thread is allowed to enter (or lock) in the
same critical section to be executed.
• It is implemented by following methods of Object class: wait(), notify(), notifyAll()

1) wait() method
• Causes current thread to release the lock and wait until either another thread invokes the
notify() method or the notifyAll() method for this object.

2) notify() method
Wakes up a single thread(arbitarilty chosen) that is waiting on this object's monitor
Syntax: public final void notify()

3) notifyAll() method
Wakes up all threads that are waiting on this object's monitor.
Syntax: public final void notifyAll()
Differences between wait and sleep methods.

wait() sleep()

wait() method releases the lock sleep() method doesn't release the lock.

is the method of Object class is the method of Thread class

is the non-static method is the static method

should be notified by notify() or notifyAll() after the specified amount of time, sleep is

methods completed.
example of inter thread communication

class Customer{ class Test{


int amount=10000; public static void main(String args[]){
final Customer c=new Customer();
synchronized void withdraw(int amount){ new Thread(){
System.out.println("going to withdraw..."); public void run(){c.withdraw(15000);}
}.start();
if(this.amount<amount){ new Thread(){
System.out.println("Less balance; waiting for deposit..."); public void run(){c.deposit(10000);}
try{wait(); }.start();
}catch(Exception e){}
} }}
this.amount-=amount;
System.out.println("withdraw completed..."); }

synchronized void deposit(int amount){


System.out.println("going to deposit...");
this.amount+=amount;
System.out.println("deposit completed... ");
notify();
} }

You might also like