0% found this document useful (0 votes)
23 views158 pages

Multi Threading

Uploaded by

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

Multi Threading

Uploaded by

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

Multithreading

Doing multiple tasks simultaneously


Or
Executing several tasks
simultaneously.
Multitasking
• Process based:
where each task is separate independent
process(OS level)

• Thread based:
where each task is a part of same program
(program level)
Applications
• To develop multimedia graphics

• To develop animations

• To develop video games

• To develop web servers and application


servers … etc..
Thread
• A separate flow of execution
for every thread … there is a job
There are two ways to define a thread
1. By extending Thread class

2. By implementing Runnable interface


An example of threaded program
class Mythread extends Thread{
public void run(){
for( int i=0;i<10;i++){
System.out.println(“Child Thread”);
}
}
}
class ThreadDemo{
public static void main(String args[]){
MyThread t=new MyThread();
t.start();
for( int i=0;i<10;i++)
System.out.println(“Parent Thread”);
}
}
Thread Scheduler
• Responsible to schedule threads.
• It is part of JVM.
• It varies from system to system.
If multiple threads are waiting to get chance
of execution then in which order thread will be
executed, is decided by Thread Scheduler.
Hence output order may vary for each
execution
Methods Defined in Thread Class
• public static Thread currentThread();
Returns: the currently executing thread

• public static int enumerate( Thread[] tarray);


tarray - an array into which to put the list
of threads
Returns: the number of threads put into
the array
• public final String getName();
Returns: this thread's name

• public final int getPriority();


Returns: this thread's priority

• public final ThreadGroup getThreadGroup(); Returns:


this thread's thread group

• public void interrupt();


used to interrupt a sleeping or waiting thread
Throws: SecurityException - if the current thread
cannot modify this thread
• public static boolean interrupted();
Returns: true if the current thread has been
interrupted; false otherwise

• public final boolean isDaemon();


Returns: true if this thread is a daemon thread;
false otherwise

• public final void join();


Throws: InterruptedException - if any thread has
interrupted the current thread. The interrupted status of
the current thread is cleared when this exception is
thrown
public final void join(long ms);
public final void join(long ms , long ns);
 Every join() method throws
InterruptedException that is checked exception
Hence compulsory to handle this exception
• public void run();
Entry point for the thread.
Description: If this thread was constructed
using a separate Runnable run object, then that
Runnable object's run method is called; otherwise,
this method does nothing and returns. Subclasses
of Thread should override this method.
• public static void yield();
Description: A hint to the scheduler that
the current thread is willing to yield its current
use of a processor. The scheduler is free to
ignore this hint

• public void start();


Start a thread by calling run() method
Throws: IllegalThreadStateException - if
the thread was already started.
• public static void sleep(long ms);
• public static void sleep(long ms, int ns);

Parameters: ms - the length of time to sleep


in milliseconds
ns- nano seconds

Throws: IllegalArgumentException - if the


value of millis is negative InterruptedException - if
any thread has interrupted the current thread.
The interrupted status of the current thread is
cleared when this exception is thrown.
• public final void setPriority(int newPriority);
Parameters: newPriority - priority to set
this thread to.. Its range is from 1 to 10
Throws: IllegalArgumentException- If the
priority is not in the range MIN_PRIORITY to
MAX_PRIORITY SecurityException - if the current
thread cannot modify this thread.
• public final void setName(String name);
Parameters: name - the new name for this
thread.
Throws: SecurityException - if the current
thread cannot modify this thread.
• public final void setDaemon(boolean on);
Parameters: on - if true, marks this thread as a
daemon thread
Throws: IllegalThreadStateException - if
this thread is alive SecurityException - if
checkAccess() determines that the current
thread cannot modify this thread.
• public final void checkAccess();
Throws: SecurityException - if the current
thread is not allowed to access this thread.
Difference b/w t.start() & t.run()
t.start()  Execution order is not fixed.
Here new Thread will be created that is
responsible for execution of run() method.

t.run()  Execution order is fixed.


A new thread won’t be created and run()
method will be executed as normal method call
by main thread.
Inside a start() method
start(){
1. Register this thread with Thread
Scheduler
2. Perform all the other mandatory activity
3. Invoke run() method
}
More about run() method
Overloading of run() method is always
possible but the start() method of thread class
can invoke no argument run() method

The other overloaded methods we have to


call explicitly like a normal method call
E.g. 1 class Mythread extends Thread{
public void run(){
System.out.println(“no argument method”);
}
public void run(int x){
System.out.println(“argument method”);
}
}
class ThreadDemo{
public static void main(String args[]){
MyThread t=new MyThread();
t.start();
}
}
Output: no argument method
E.g. 2
class Mythread extends Thread{
}
class ThreadDemo{
public static void main(String args[]){
MyThread t=new MyThread();
t.start();
}
}
Output: we won’t get any output because
Thread class run() method has empty
implementation
Overriding start() method
E.g. 1 class Mythread extends Thread{
public void start(){
System.out.println(“start method”);
}
public void run(){
System.out.println(“run method”);
}
}
class ThreadDemo{
public static void main(String args[]){
MyThread t=new MyThread();
t.start();
System.out.println(“main method”);
}
}
Output: start method
main method
E.g. 2 class Mythread extends Thread{
public void start(){
super.start();
System.out.println(“start method”);
}
public void run(){
System.out.println(“run method”);
}
}
class ThreadDemo{
public static void main(String args[]){
MyThread t=new MyThread();
t.start();
System.out.println(“main method”);
}
}
Output: start method main method run method
main method run method start method
run method start method main method
Life cycle of a Thread
MyThread t=new MyThread();

New / t.start()
Born Ready/
Running
Runnable If Thread
Scheduler

If run d
meth etes
comp
allocate
processors

()
o
l
Dead
Some important points
 When a thread is started once it can’t be restarted
again. If we will try to restart then exception will be
raised saying…
…IllegalThreadStateException
It’s an run time exception
public static void main(String args[])
{
Thread t=new Thread();
t.start();
t.start();//Here exception will be raised
}
 We can define a thread by implementing
Runnable interface
Runnable interface doesn’t contain start()
method. It contains only run() method.
--------------------------------------------
class MyRunnable implements Runnable{
public void run(){
for( int i=0;i<10;i++)
System.out.println(“Child Thread”);
}
} Job of the thread
Executed by child
thread
class ThreadDemo{
public static void main(String args[]){
MyRunnable r=new MyRunnable();
Thread t=new Thread(r);
t.start();
for(int i=0;i<10;i++)
System.out.println(“main thread”);
}
}
Output: we will get mixed output …means n
number of outputs are possible
class ThreadDemo{
public static void main(String args[]){
MyRunnable r=new MyRunnable();
Thread t1=new Thread();
Thread t2=new Thread(r);
}
}
Case study
----------------------------
1. t1.start();
A new thread will be created and which is
responsible for execution of thread class run()
method which has empty implementation
2. t1.run();
no new thread will be created and thread
class run() method will be executed just like
normal method call.
3. t2.start();
A new thread will be created which is
responsible for execution of MyRunnable run()
method.
4. t2.run();
no new thread will be created and
MyRunnable run() method will be executed just
like normal method call.
5. r.start();
We will get compile time error because
Runnable interface doesn’t have start() method
6. r.run();
MyRunnable run() method will be
executed like normal method call and no new
thread will be created.

 We should define a thread by implementing


Runnable interface because by this way we
won’t miss inheritance property.
Constructors of Thread class
1. Thread t=new Thread();
2. Thread t=new Thread(Runnable r);
3. Thread t=new Thread(String name);
4. Thread t=new Thread(Runnable r, String name);
5. Thread t=new Thread( ThradGroup g, String name);
6. Thread t=new Thread( ThreadGroup g, Runnable r);
7. Thread t=new Thread( ThreadGroup g, Runnable r,
String name);
8. Thread t=new Thread( ThreadGroup g, Runnable r,
String name, long stack_size);
Extra  Thread t=new Thread(Thread r);
Every Thread has a name. May be default
or provided by programmer
• public final String getName();
• public final void setName(String name);
• public static Thread currentThread();
-----------------
A sample program

class MyThread extends Thread{

}
Class Test{
public static void main(String args[]){
System.out.println(“name of current
thread:”+Thread.currentThread().getName());
MyThread t=new MyThread();
System.out.println(“name of child thread:”+t.getName());
Thread.currentThread().setName( “cse”);
System.out.println(“now name of current
thread:”+Thread.currentThread().getName());
}
}
Output : name of current thread : main
name of child thread : Thread-0
now name of child thread : cse
Thread Priorities
• Every thread in java has some priority either
provided by programmer or JVM.
• Priority range is 1 to 10.
• Thread Scheduler will use priorities while
allocating processor.
• Thread with highest priority will get chance first
to execute
• If priorities are same then we can’t expect that
which thread will get chance first.
• The default priority for main thread is 5 but
for all remaining threads default priority will
be inherited from parent thread to child
thread.
• These are the methods to get and set priority
of a thread
 public final int getPriority();
 public final void setPriority(int p);
• Some predefined constants for priority
1. Thread.MIN_PRIORITY for 1
2. Thread.MAX_PRIORITY for 10
3. Thread.NORM_PRIORITY for 5
Sample program for Priority Demo
public static void main(String args[]){
System.out.println(“current thread priority:”+
Thread.currentThread().getPriority());// 5
Thread.currentThread().setPriority(12); //runtime
exception
Thread.currentThread().setPriority(7);
MyThread t=new MyThread();
t.start();
System.out.println(“current thread priority:”+
t.getPriority());// 7
}
Thread main
class Thread

e ad
ss

thr
c l a

nt
nt

e
Pare

Par
MyThread t=new
MyThread();
Example on Priority
class Mythread extends Thread{
public void run(){
for( int i=0;i<10;i++){
System.out.println(“Child Thread”);
}
}
}
class ThreadPriorityDemo{
public static void main(String args[]){
MyThread t=new MyThread();
t.setPriority(10);
t.start();
for( int i=0;i<10;i++)
System.out.println(“Parent Thread”);
}
}
Output: In this program output should be only one
Note:
In the previous program at some system output
may vary for each execution because some
systems don’t follow priority order
Preventing Thread execution temporarily

• Methods
1. yield();
2. join();
3. sleep();
1. yield() method
• This method causes to pause the current
executing thread to give the chance to other
waiting thread of same priority. If there is no
waiting thread or all the waiting threads
having low priority then same thread can
continue its execution.
• If multiple threads are waiting with same
priority then which thread will get chance , it
depends on thread scheduler
• The thread which is yielded ,when again it will get
chance ,it depends on thread scheduler
public static native void yield();
Sample program
-----------------
Class MyThread extends Thread{
public void run(){
for(int i=0;i<10;i++){
System.out.println(“child thread”);
Thread.yield();
}
} Line 1
class ThreadYieldDemo{
public static void main(String args[]){
MyThread t=new MyThread();
t.start();
for(int i=0;i<10;i++){
System.out.println(“parent thread”);
}
}
}
In this program if we comment Line 1 then the both threads
will be executed simultaneously and we can’t expect that
which thread will complete its execution first else child
thread always calls yield() method so main thread will get
more chance .Hence chance of completion of main thread is
more than child thread
Impact of yield() method on life cycle of a
Thread
MyThread t=new MyThread(); Thread.yield();

New / t.start();
Born Ready/
Running
Runnable
If Thread

If run d
meth etes
comp
Scheduler
allocate

()
o
l
processors

Dead
2. join() method
• If thread wants to wait until completing some
other thread then we can go for join()
method. For example a thread t1 wants to
wait until completing the execution of thread
t2 then t1 has to call t2.join();
eg.
Venue fixing Wedding card Wedding card
activity(t1) printing(t2) distribution(t3)
t2 t2
t1

t1.join(); t2.join();
In the above example t2 has to wait until
venue fixing thread t1 completion, hence t2 has
to call t1.join() method.
Wedding card distribution thread t3 has to
wait until completion of wedding card printing,
hence t3 has to call t2.join() method.
 public final join();
 public final join(long ms );
 public final join(long ms , int ns);
• Every join() method throws
InterruptedException that is checked
Exception hence compulsory to handle
An example for join() method
class MyThread extends Thread{
public void run(){
for( int i=0;i<10;i++){
System.out.println(“child thread”);
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
}
}
}
class ThreadJoinDemo {
public static void main(String args[]){
MyThread t=new MyThread();
t.start();
t.join();
Line 1
//t.join(2000);
//t.join(2000,80);
for(int i=0;i<10;i++)
System.out.println(“child thread”);
}
}
//here main thread will wait until completion of child
thread
 If we comment Line 1 then both main
and child thread will be executed simultaneously
and we can’t except exact output.

 If we don’t comment Line 1 then main


thread calls join() on child thread ,hence main
thread will wait until completion of child thread
Impact of join() method on life cycle of a
Thread
MyThread t=new MyThread(); If Thread
Scheduler allocate
New / processors
t.start();
Born Ready/
Running
Runnable

If run d
meth etes
comp
t e s or ted
l e rup
omp ires or ot inter

()
c

o
2
If t e exp ead g

l
ti m th r ( ) ; 00); 00);
If i ti ng o in (10 0,1
a j
If w t2. .join (200
Waiting state T2 .join
T2 Dead
(Blocked for joining)
Another example
class MyThread extends Thread{
static Thread mainThread;
public void run(){
try{
mainThread.join();
}
catch(InterruptedException e){}
for(int i=0;i<10;i++)
System.out.println(“child thread”)
}
}
class ThreadJoinDemo1{
public static void main(String args[]) throws
InterruptedException {
MyThread.mainThread = Thread.currentThread();
MyThread t=new MyThread();
t.start();
for(int i=0;i<10;i++){
System.out.println(“main thread”);
Thread.sleep(2000);
}
}
}

In this example child thread calls join() method on main thread,
hence child thread has to wait until completion of main thread
Important point regarding join() method

• If main thread calls join() method on child


thread and child thread calls join() method on
main thread ….. Then both thread will wait for
each other forever. This is just like deadlock.

• If a thread calls join() method for itself ,this is


also like deadlock.
An example for deadlock
class DeadLockDemo{
public static void main(String args[])throws
Exception{
Thread.currentThread().join();
}
}

main thread This line is executed


by main thread
this program will never terminate
3. sleep() method
• If a thread don’t want to perform any operation
for a particular amount of time then sleep()
method is useful .
 public static native void sleep (long ms);
 public static void sleep(long ms ,int ns);
• Every sleep() method throws
InterruptedException which is checked
exception , handling is compulsory.
Those methods which are
not implemented in java
 An example for sleep() method
class SlideRotator{
public static void main(String args[])
throws InterruptedException{
for(int i=1;i<=10;i++){
System.out.println(“slide_”+i);
Thread.sleep(2000);
}
}
}
How a thread can interrupt another thread!
• A thread can interrupt a sleeping or waiting thread by using interrupt() method of Thread
class
 public void interrupt();
An example
-----------------------------
class MyThread extends Thread{
public void run(){
try{
for(int i=0;i<10;i++){
System.out.println(“I am lazy”);
Thread.sleep(1000);
}
}
catch(InterruptedException e){
System.out.println(“I got Interrupted”);
}
}
}
class ThreadInterruptDemo{
public static void main(String args[]){
MyThread t=new MyThread();
t.start(); Line 1
t.interrupt();
System.out.println(“End of main thread”);
}
}
 If we comment Line 1 then main thread will not
interrupt child thread. Hence child thread will execute
10 times else child thread will not execute 10 times.
• When ever we are calling interrupt() method if
the target thread is not sleeping or waiting then
there is no impact of interrupt() call immediately.
Interrupt call will wait until target thread enters
into waiting state. As the target thread enters
into waiting or sleeping state ,immediately
interrupt call will interrupt the target thread.
• If target thread will never enters into waiting or
sleeping state then its life time there is no
impact of interrupt call. In this case interrupt call
will be wasted.
 Example
class MyThread extends Thread{
public void run(){
for( int i=1;i<=1000;i++)
System.out.println(“I am lazy_”+i);
System.out.println(“I am going to sleep);
try{
Thread.sleep(1000);
}
catch(InterruptedException e){
System.out.println(“I got interrupted”);
}
}
}
class ThreadSleepDemo{
public static void main(String args[]){
MyThread t=new MyThread();
t.start();
t.interrupt();
System.out.println(“End of main thread”);
}
}
Synchronization
• synchronized is a modifier applicable only for
methods and blocks but not for classes and
variables.
• If multiple threads are trying to operate
simultaneously on same java object then there
may be a chance of data inconsistency problem.
 To overcome from this we should go for
synchronized keyword.
• If a method or block as synchronized then method
or block on a given object. So that data
inconsistency problem can be resolved.
• The main advantage of syschronized keyword is we
can resolve data inconsistency problem but the
main disadvantage of this keyword is, it increases
waiting time of threads and decreases performance.
• Internally synchronization concept is implemented
by using lock concept. Every object in java has a
unique lock. When we use syschronized keyword
then only lock concept comes into picture. at a time
only one thread is allowed to execute that
• If a thread wants to execute a synchronized
method on the given method, first it has to get
lock of that object. Once it has got the lock then it
is allowed to execute any synchronized method
on that object. Once method execution completes
automatically releases the lock. Acquiring and
releasing lock internally taken care by JVM.
• While a thread executing a synchronized method
on a given object, the remaining threads are not
allowed to execute any synchronized method
simultaneously on the same object but remaining
threads are allowed to execute non-synchronized
methods simultaneously.
class X{
synch m1();
synch m2();
m3();
}
m1()
-----------------------------------------------------------
t2 X t1 l(x)
sta ng
iti
te
Wa

m3
2 ()

()
Wa t3 m
iti
sta ng
te t4
This thread will
not go in
waiting state
Non-
Synchr
synchr
onized
onized
area
area

Object

These method can be These methods can be


accessed by any number accessed by only one
of threads simultaneously thread at a time
class X{
synchronized area{
where ever we are performing update
operations ( add , remove , delete , replace ) i.e.
where state of object is changing.
}
non-synchronized area{
where ever object state won’t changed ,
like read operation.
}
}
class Reservation {
non-synchronized
checkAvailability(){
_______________
_______________
}
synchronized
bookTicket(){
_______________
_______________
}
}
 Example
class Display {
public synchronized void wish(String name){
for(int i=0;i<10;i++){
System.out.print(“Good morning:”);
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
System.out.println(name);
}
}
}
class MyThread extends Thread{
Display d ; String name ;
MyThread(Display d1, String name1){
d=d1; name=name1;
}
public void run(){
d.wish(name);
}
}
case 1:
class SynchronizedDemo {
public static void main(String args[]){
Display d=new Display();
MyThread t1=new MyThread( d, ”Sir”);
MyThread t2=new MyThread( d, ”ma’am”);
t1.start();
t2.start();
}
}
 If we are not declaring wish() method as synchronized then both threads
will be executed simultaneously and we will get mixed(irregular) output.

 If we are not declaring wish() method as synchronized then at a time


only one thread will be executing on the given Display object. Hence we
will get regular output.
case 2:
class SynchronizedDemo {
public static void main(String args[]){
Display d1=new Display();
Display d2=new Display();
MyThread t1=new MyThread( d1, ”Sir”);
MyThread t2=new MyThread( d2, ”ma’am”);
t1.start();
t2.start();
}
}
 Even though wish() method is synchronized , we will get
irregular outputs because threads are operating on different
objects.
 Conclusion
If multiple threads are operating on same
java object then synchronization is required.
If multiple threads are operating on
multiple java objects then synchronization is
required.
Class level lock
• Every class in java has a unique lock which is
nothing but class level lock.
• If a thread wants to execute a static
synchronized method then thread requires
class level lock. After getting this lock thread is
allowed to execute any static synchronized
method of that class.
• Once method execution completes
automatically thread releases the lock.
class X{
static synch m1();
static synch m2();
static m3();
synch m4();
m5();

} -----------------------------------------------------------
m1()
t2 X t1 cl(x)
sta ng
iti
te
Wa

m5
2 ()

()
t3 m
m3 ( )

m4
Wa
iti
t6
()
sta ng
te
t5
t4 This thread will
not go in waiting
state
 While a thread executing static synchronized
method , the remaining threads are not allowed
to execute any static synchronized method of
that class simultaneously. But remaining threads
are allowed to execute the following methods
simultaneously.
1. normal static methods.
2. synchronized instance methods.
3. normal instance methods.
 Example
class Display {
public void displayn(){
for(int i=1;i<=10;i++){
System.out.println(i);
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
System.out.println(name);
}
}

public void displayc(){


for(int i=65;i<=74;i++){
System.out.println(char(i));
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
System.out.println(name);
}
}

}
class MyThread1 extends Thread{
Display d;
Mythread1(Display d){
this.d=d;
}
public void run(){
d.displayn();
}
}
class MyThread2 extends Thread{
Display d;
Mythread2(Display d){
this.d=d;
}
public void run(){
d.displayc();
}
}
class SynchronizedDemo {
public static void main(String args[]){
Display d=new Display();
MyThread1 t1=new MyThread1(d);
MyThread2 t2=new MyThread2(d);
t1.start();
t2.start();
}
}
 There is no fixed output . It will give mixed (irregular)
output.
 If we replace displayn() and displayc() methods by…..
public synchronized void displayn(){}
public synchronized void displayc(){}
Then we will get regular output.
Synchronized block concept
• If very few lines of code requires
synchronization then it is not recommended
to declare entire method as synchronized. We
have to enclose those few lines of the code by
using synchronized block.
• The main advantage of synchronized block
over synchronized method is, it reduces
waiting time of threads and increases
performance of the system.
Declaring a synchronized block
• We can declare synchronized block as follows
1. synchronized(this){
______;
If a thread got lock of current object
______; then only it is allowed to execute
this area
}
2. synchronized( ob ){
If a thread got lock of a particular
______; object ‘ob’ then only it is allowed to
______; execute this area

}
3. synchronized( Display.class ){
If a thread got class level lock of
______; Display class then only it is allowed
______; to execute this area

}
Examples 1
class Display{
public void wish(String name){
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;// 1 lakh lines of code
synchronized(this){
for(int i=1;i<=10;i++){
System.out.print(“Hello:”);
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
System.out.println(name);
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;// 1 lakh lines of code
}
}
class MyThread extends Thread{
Display d;
String name;
MyThread(Display d, String name){
this.d=d;
this.name=name;
}
public void run(){
d.wish(name);
}
}
class SynchronizedDemo {
public static void main(String args[]){
Display d=new Display();
MyThread t1=new MyThread(d,”sir”);
MyThread t2=new MyThread(d,”ma’am”);
t1.start();
t2.start();
}
}
 Here we will get regular output. If display objects
are different, then for regular output class level lock is
required.
Example 2
class Display{
public void wish(String name){
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;// 1 lakh lines of code
synchronized(Display.class){
for(int i=1;i<=10;i++){
System.out.print(“Hello:”);
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
System.out.println(name);
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;// 1 lakh lines of code
}
}
class MyThread extends Thread{
Display d;
String name;
MyThread(Display d, String name){
this.d=d;
this.name=name;
}
public void run(){
d.wish(name);
}
}
class SynchronizedDemo {
public static void main(String args[]){
Display d1=new Display();
Display d2=new Display();
MyThread t1=new MyThread(d1,”sir”);
MyThread t2=new MyThread(d2,”ma’am”);
t1.start();
t2.start();
}
}
 Here also we will get regular output because we
have used class level lock.
We should know this also
• Lock concept is applicable for objects or class
but not for primitive data types.

int x=10;
synchronized(x){
__________;
__________; We will get
compile time
} error.
Can a thread acquire more than one lock
simultaneously ?
• Yes, a thread can acquire n number of locks simultaneously depending
upon conditions.
Example X x=new X();
x.m1();
class X{
public synchronized void m1(){
Y y=new Y();
Here thread has lock of X
synchronized(y){
Z z=new Z();
Here thread has lock of X,Y
synchronized(z){
_________;
_________;
}
} Here thread has lock of X,Y&Z
}
}
Inter thread communication
• Two threads can communicate each other by
using wait(), notify(), notifyAll() methods.
• The thread which expects updation is
responsible to call wait() method then
immediately thread will enter into waiting state.
• The thread which is responsible for updation,
has to call notify() method then waiting thread
will get notification and will continue its
execution with those updated items.
t1 t2

wait() notify()
----------------------------------------------
 Here t1 needs updation hence it has to call wait()
method & t2 will update, hence after updating t2
has to call notify() method.
You should know this also
• wait() , notify() , notifyAll() methods are
present in class Object but not in class Thread,
because thread can call these methods on any
java objects.
t2
t1 PostBox
Stack
Queue .wait()
Student
Customer .notify()
• To call wait() , notify() , notifyAll() methods on any
object ,thread should be owner of that object i.e.
thread should have lock of that object i.e. thread
should be inside synchronized area. Hence we can call
wait() , notify(), notifyAll() methods only from
synchronized area , otherwise we will get runtime
exception ….saying IllegalMonitorStateException
• If a thread calls wait() method on any object it
immediately releases the lock of that particular object
and enters into waiting state.
• If a thread calls notify() method on any object it
releases the lock of that object but not immediately.
 Except wait() , notify() , notifyAll() there is no other
method where thread releases the lock .
Impact of wait() & notify() methods on life
cycle of a Thread
MyThread t=new MyThread(); If Thread
Scheduler allocate
New / processors
t.start();
Born Ready/
Running
Runnable

If run d
meth etes
ad

comp
e
t hr

()
o
ng ock

l
ti
ai e l

;
0)
00 0);
w
If t th

10
.w it ;
t( 2 0
t2 .wa it()

0,
ai (10
go

t2 .wa
t2
Another Dead
waiting state 1. If waiting thread
to get lock got notification Waiting
2. if time expires state
3. If waiting thread
got interrupted
 Example 1
class ThreadA{
public static void main(String args){
ThreadB b=new ThreadB();
b.start();
System.out.println(“sum=”+b.total);
}
}
class ThreadB{
int total=0;
public void run(){
for(int i=1;i<=100;i++)
total=total + i ;
}
}
 output: Here output may come 0 or 5050 or in between 0 and 5050.
 Example 2
class ThreadA{
public static void main(String args) throws InterruptedException{
ThreadB b=new ThreadB();
b.start();
Thread.sleep(2000);
System.out.println(“sum=”+b.total);
}
}
class ThreadB{
int total=0;
public void run(){
for(int i=1;i<=100;i++){
total=total + i ;
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;//1 crore lines code
}
}
Now let’s use wait() and notify methods
class ThreadA{
public static void main(String args[]){
ThreadB b=new ThreadB();
b.start();
synchronized(b){
System.out.println(“main thread trying to call
wait() method”); 1
b.wait();
4 notification”);
System.out.println(“main thread got
System.out.println(“sum=”+ b.total);
}
} 5
}
class ThreadB{
int total=0;
public void run(){
synchronized(this){
System.out.println(“child thread starts
execution”); 2
for(int i=1;i<=100;i++)
total+=i;
System.out.println(“child thread trying
to give notification”); 3
this.notify();
}
}
}
Few more facts
• Most of the time main thread gets chance to
execute.
• If child thread got chance first then if it had
given notification but main thread was
sleeping, then main thread has to sleep life
long.
Producer Consumer Problem
• Producer thread is responsible to produce items
to the queue & consumer thread is responsible
to consumes the items from queue . If queue is
empty then consumer thread calls wait() method
& enters into waiting state. After producing items
to the queue producer thread is responsible to
call notify() method. Then waiting consumer
thread will get notification and continues its
execution with updated items.
Queue q
Producer thread Consumer thread

class ConsumerThread {
class ProducerThread {
Consume(){
Produce(){
Synchronized(q){
Synchronized(q)
if( q is
{
empty)
Produce
q.wait()
item to the queue
else
q.notify()
consume items
}
}
}
}
}
}
Difference between notify() & notifyAll()

• We can use notify() method to give notification for


only one waiting thread. If multiple threads are
waiting then using notify() method only one thread
can be notified and remaining threads have to wait
for further notifications. Which thread will be
notified ,we cant expect ,it depends on JVM.
• We can use notifyAll() method to give notification
for all waiting threads of that particular object. Even
then multiple threads got notified but execution will
be performed by only one thread , because thread
requires lock and only one lock is available.
 On which object we are calling wait() method,
thread requires the lock of that particular object .
For example if we are calling wait() method on s1
then we have to get lock of s1 object but not s2
object.
Here we will get
Stack s1=new Stack(); runtime exception:
Stack s2=new Stack(); IllegalMonitorStateException

synchronized(s1){ synchronized(s1){
_____; _____;
s2.wait(); s1.wait();
_____; _____;
} }
Deadlock
• If two threads are waiting for each other
forever , such type of infinite waiting is called
deadlock.
• synchronized keyword is the only reason for
deadlock situation , hence while using
synchronized keyword , we have to take
special care.
• There are no resolution techniques for
deadlock but several prevention techniques
are available
 Example
class A{
public synchronized void d1(B b){
System.out.println(“Thread1 starts execution of d1()
method”);
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
System.out.println(“Thread1 trying to call B’s last()
method”);
b.last();
}
public synchronized void last(){
System.out.println(“Inside A, this is last() method”);
}
class B{
public synchronized void d2(A a){
System.out.println(“Thread2 starts execution of d2()
method”);
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
System.out.println(“Thread2 trying to call A’s last()
method”);
a.last();
}
public synchronized void last(){
System.out.println(“Inside B, this is last() method”);
}
}
class DeadLockDemo extends Thread {
A a=new A();
B b=new B();
public void m1(){
this.start();
a.d1(b);
This line is executed
} by main thread
public void run(){ This line is executed
b.d2(a); by child thread
}
public static void main(String args[]){
DeadLock d=new Deadlock();
d.m1();
}
Deadlock v/s Starvation
• Long waiting of a thread where waiting never
ends is called deadlock.
• Long waiting of a thread where waiting ends at
certain point is called starvation.
• Example :
Low priority thread has to wait until
completion of all high priority threads. It may be
long waiting time but ends at certain point which
is nothing but starvation.
Daemon threads
• The thread which is executing in background is
called Daemon thread .
• Examples : Garbage Collector , Attach Listener,
Signal Dispatcher etc.
• The main objective of Daemon thread is to
provide supports for non daemon threads.
• For example if main thread runs with low
memory then JVM runs Garbage Collector to
destroy useless objects so that number of bytes
of free memory will be improved. With this free
memory main thread can continue its execution.
• Usually daemon threads having low priority but
based on out requirement Daemon thread can
run with high priority also.
 public boolean isDaemon();
 public void setDaemon( boolean b);
true Daemon
false non -Daemon

• We can check Daemon nature of a thread by


using isDaemon() method of Thread class.
• We can change Daemon nature of a thread by
using setDaemon() method of Thread class.
Important point
• Changing daemon nature of a thread is
possible before starting . After starting if we
try to change Daemon nature then we will get
runtime exception saying
IllegalThreadStateException
Default Nature
• By default main thread is always non-daemon
and for all remaining threads daemon nature
will be inherited from parent to child thread
i.e. if parent thread is daemon then child
threads are also daemon and if parent thread
is non-daemon then child threads are also
non-daemon.
• Note :
It is not possible to change daemon nature of main thread
because it is already started by JVM at beginning.
• Example
class MyThread extends Thread{
}
class Test {
public static void main(String args[]){

System.out.println( Thread.currentThread().isDaemon());//false
MyThread t=new MyThread();
System.out.println( t.isDaemon() );//false
t.setDaemon(true);
System.out.println( t.isDaemon() );//true
}
}
• Whenever last non-daemon thread terminates, automatically all
daemon threads will be terminated irrespective of their positions.
• Example
class MyThread extends Thread{
public void run(){
for(int i=0;i<10;i++){
System.out.println(“child thread”);
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
}
}
}
class DaemonThreadDemo {
public static void main(String args[]){
MyThread t=new MyThread();
t.setDaemon(true);
t.start(); Line 1

System.out.println(“End of main thread”);


}
}
 If we don’t comment Line 1 then both main and
child threads are non-daemon and hence both
threads will be executed until their completion.
 If we comment Line 1 then main thread is
non-daemon and child threads is daemon and
hence whenever main thread terminates
automatically child thread also terminates.
Green Thread
• Java multithreading concept is implemented by
following two models
1. Green Thread Model
2. Native OS Model.
Green Thread Model:
The thread which is managed completely by JVM
without taking underlying OS support is called Green Thread.
Very few Operating systems like sun solaria, provides support
for green threads. Any way green thread model is deprecated
and not recommended to use.
 Native OS Model
The thread which is managed by JVM with
the help of underlying OS support, is called
Native OS Model.
All windows based OS provide supports for
Native OS Model.
Some other methods
• We can stop a thread execution by using stop()
method of java class.
 public void stop();
If we call stop() method, immediately thread
will enter into dead state . Anyway stop()
method is deprecated and not recommended to
use.
How to suspend and resume a thread?
 public void suspend();
 public void resume();
• We can suspend a thread by using suspend()
method of the thread class. After calling
suspend() method immediately thread enters
into suspended state. We can resume a
suspended thread by using resume() method of
thread class. After calling resume() method the
suspended thread can continue its execution.
• Any way these methods are deprecated and not
recommended to use.
Thread Group
• Based on functionality we can group threads
into a single unit which is nothing but thread
group i.e. ThreadGroup contains a group of
threads.
• In addition to threads ThreadGroup can also
contain sub Thread groups.
• This is a ThreadGroup which contains threads and
sub thread group.
t2 t3
t1 t4

t5 t6

Sub thread group

Thread group
• The main advantage of maintaining threads in the form of
ThreadGroup is ,we can perform common operations very easily.
main method
main thread
 class Test{ main ThreadGroup
public static void main(String args[]){
System.out.println(
Thread.currentThread().getName());//main

System.out.println( Thread.currentThread().getThreadGroup().getNam
e());//main

System.out.println( Thread.currentThread().getThreadGroup().getParen
t().getName());//system
}
}
• Every thread in java belongs to some group.
main thread belongs to main group.
• Every thread group in java is the child group of
system group either directly or indirectly.
Hence System Group acts as root for all
ThreadGruops in java.
• System Group contains several system level
threads like..
1. Finalizer (Garbage Collector)
2. Reference Handler
3. Signal Dispatcher
4. Attach Listener
System

Reference Handler
main
ThreadGroup Finalizer Signal Dispatcher

Attach Listener
main thread
sub
Thread-0 ThreadGroup

t1 t2
• ThreadGroup is a java class present in
java.lang package and direct child class of
Object class.
Object

ThreadGroup
Constructors of ThreadGroup
1. ThreadGroup g=new ThreadGroup(String name);
creates a new thread group with the specified
group name. The parent of new group is the thread
group of currently executing thread.
Example ThreadGroup g=new ThreadGroup(“first”);
2. ThreadGroup g=new ThreadGroup( ThreadGroup
pg ,String name);
Example ThreadGroup g1=new ThreadGroup (g ,
“first ”);
• Example
class Test {
public static void main(String args[]) {
ThreadGroup g1=new ThreadGroup( “first
thread”);

System.out.println( g1.getParent().getName());//main
ThreadGroup g2=new ThreadGroup(g1, “second
thread”);
System.out.println( g2.getParent().getName());//
first group
}
}
Important methods of ThreadGroup class
1. String getName(); used to get name of the thread group.
2. int getMaxPriority();  used to find priority of a thread
group.
3. void setMaxPriority(int p);  used to set maximum priority
of a thread group.
4. ThreadGroup getParent();  used to get parent group of
current thread group.
5. void list();  it prints information about thread group in the
console.
6. int activeCount();  returns number of active threads
present in thread group.
7. int enumerate(Thread t[]);  to copy all active threads of
this thread group into provided thread array. In this case
8. int enumerate(ThreadGroup t[]);  to copy all
active sub thread groups into ThreadGroup array.
9. Boolean isDaemon();  to get daemon nature of a
thread group.
10. Void setDaemon( boolean b);  to change
daemon nature of a thread group.
11. Void interrupt();  to interrupt all waiting
threads of a thread group.
12. Void destroy();  to destroy thread group and its
sub thread groups.
13. Int activeGroupCount();  it returns no. of active
thread groups present in current thread group.
Example
class MyThread extends Thread {
MyThread(ThreadGroup g, String name){
super(g , name);
}
public void run(){
System.out.println(“child thread”);
try{
Thread.sleep(2000);
}
catch(InterruptedException a){}
}
}
class ThreadGroupDemo {
public static void main(String args[]) throws Exception {
ThreadGroup pg=new ThreadGroup(“parent group”);
ThreadGroup cg=new ThreadGroup(pg,“child group”);
MyThread t1=new MyThread(pg,”childthread1”);
MyThread t2=new MyThread(pg,”childthread2”);
t1.start();
t2.start();
System.out.println( pg.activeCount() );//2
System.out.println( pg.activeGroupCount() );//1
pg.list();
Thread.sleep(10000);
System.out.println( pg.activeCount() );//0
System.out.println( pg.activeGroupCount() );//1
pg.list();
}
Write a program to display all active threads
belongs to system group and its child group.
class ThreadGroupDemo {
public static void main(String args[]) {
ThreadGroup system=
Thread.currentThread().getThreadGroup().getParent();
Thread t[]=new Thread[ system.activeCount()];
system.enumerate(t);
for(Thread t1:t)
System.out.println(t1.getName()+”--- “ + t1.isDaemon());
}
}
 output:
Reference Handler---true
Finalizer---true
Signal Dispatcher---true
Attach Listener---true
main----false
java.util.concurrent package
• Problems with traditional synchronized keyword
1. We are not having any flexibility to try for a lock without
waiting.
2. There is no way to specify maximum waiting time for a
thread to get lock so that thread will wait until getting
lock ,which may create performance problem ,that may
cause deadlock.
3. If a thread releases lock then which waiting thread will get
that lock ,we are not having any control on this.
4. There is no API support to list out all the waiting threads
for a lock.
5. The synchronized keyword we have to use either at
method level or within the method and it is not possible to
use across multiple methods.
• To overcome of these problems, we can go for
java.util.concurrent.locks package.
It provide several enhancements to the programmer to
provide more control on concurrency

-----------
Lock interface
• Lock object is similar to implicit lock acquired by a
thread to execute synchronized block.
• Lock implementations provide more operations
than traditional implicit locks.
Important methods of Lock interface
1. void lock();
we can use this method to acquired a lock. If lock is already available
then immediately current thread get the lock. If lock is not already
available then it will wait until getting lock. It has same behaviour as
traditional synchronized keyword.
2. boolean tryLock();
To acquired the lock without waiting.
If lock is available then thread acquires that lock and returns true. If
lock is not available then this method returns false and can continue its
execution without waiting. In this case thread will never be in waiting state.
if( l.tryLock()){
perform safe operations.
}
else{
perform alternative operations
}
3. boolean tryLock(long time , TimeUnit unit);
If lock is available then thread will get lock and continue its
execution. If lock is not available then thread will wait until
specified amount of time . Still if lock is not available then thread
can execute alternative operations.
TimeUnit: It is an enum present in java.util.concurrent package.
enum TimeUnit{
NANOSECONDS,
MRCROSECONDS,
MILLISECONDS,
SECONDS,
MINUTES,
HOURS,
DAYS;
}
e.g if(l.tryLock(1000,TimeUnit.MILLISECONDS)){
}
4. void lockInterruptibly();
acquires the lock if it is available and returns
immediately.
If the lock is not available then it will wait,
while waiting if thread will be interrupted then
then thread won’t get lock.
5. void unlock();
To call this method compulsory current
thread should be owner of the lock otherwise we
will get runtime exception saying….
IllegalMonitorStateException
Reentrantlock class
• It is implementation class of Lock interface and
direct child class of Object class.
Lock interface
Object class

ReentrantLock
ReentrantLock l=new ReentrantLock();
Reentrant means, a thread can acquire same lock
multiple times without any issue.
 Internally ReentrantLock , increment thread’s
personal count when thread calls lock() method and
decrements personal count value whenever thread
calls unlock() method. All locks will be released if count
reaches to zero. false  which waiting thread will
get chance ,cant expect
 Constructors
-----------------------
1. ReentrantLock l=new ReentrantLock();
creates an instance of ReentrantLock.
2. ReentrantLock l=new ReentrantLock( boolean
fairness);
creates an instance of ReentrantLock withwaiting
true Longest giventhread
will get chance(FCFS)
fairness policy.
Important methods of ReentrantLock class

1. void lock();
2. boolean tryLock();
3. boolean tryLock(long time , TimeUnit unit);
4. void lockInterruptibly();
5. void unlock();
---------------------
6. int getHoldCount(); returns no. of holds of this
lock by current thread.
7. boolean isHeldByCurrentThread(); returns true
iff lock is hold by current thread.
8. int getQueueLength(); returns no. of threads
waiting for the lock.
9. Collection getQueuedThreads(); returns a
collection of threads which are waiting to get lock.
10. boolean hasQueuedThreads (); returns true if
any thread waiting to get lock.
11. boolean isLocked(); returns true if lock is
acquired by some thread.
12. boolean isFair(); returns true if fairness policy
is set with true value.
13. Thread getOwner(); returns thread which
acquired the lock.
Using ReentrantLock instead of
synchronized keyword
import java.util.concurrent.locks.*;
class Display {
ReentrantLock l=new ReentrantLock();
public void wish(String name){
l.lock();
Line 1
for(int i=0;i<10;i++){
System.out.print(“Good morning”);
try{
Thread.sleep(2000);
}
catch(InterruptedException e){}
System.out.println(name);
} Line 2
l.unlock();
}
}
class MyThread extends Thread {
Display d;
String name;
MyThread(Display d1 , String name1){
d=d1;
name=name1;
}
public void run(){
d.wish(name);
}
}
class ReentrantLockDemo {
public static void main(String args[]) {
Display d=new Display();
MyThread t1=new MyThread( d,”ravi”);
MyThread t2=new MyThread(d,”ram”);
t1.start();
t2.start();
}
}
 If we comment Line 1 and Line 2 then the threads
will be executed simultaneously and we will get
irregular output else we will get regular output
Demo program for tryLock() method
import java.util.concurrent.locks.*;
class MyThread extends Thread {
static ReentrantLock l=new ReentrantLock();
MyThread(String name){
super(name);
}
public void run(){
if(l.tryLock()){
System.out.println( Thread.currentThread().getName()+”--- got lock
and performing safe operations.”);
try{
Thread.sleep(2000);
}
catch(Exception e) {}
l.unlock();
}
else {
System.out.println( Thread.currentThread().getName()+”---
unable to get lock and hence performing alternative operations.”);
}
}
}
class ReentrantLockDemo {
public static void main( String args[]) {
MyThread t1=new MyThread(“First Thread”);
MyThread t2=new MyThread(“Second Thread”);
t1.start();
t2.start();
}
}
 output: First Thread ---got the got lock and performing safe operations.
Second Thread --- unable to get lock and hence performing alternative
operations.
Demo program for tryLock() method with time period
import java.util.concurrent.*;
import java.util.concurrent.locks*;
class MyThread extends Thread {
static ReentrantLock l=new ReentrantLock();
MyThread(String name){
super(name);
}
public void run(){
do{
try{
if(l.tryLock(5000,TimeUnit.MILLISECONDS)){
System.out.println( Thread.currentThread().getName()+”--- got lock.”);
Thread.sleep(30000);
l.unlock();
System.out.println( Thread.currentThread().getName()+”--- releases lock.”);
break;
}
else{
System.out.println( Thread.currentThread().getName()
+” --- unable to get lock and will try again.”);
}
}
catch(Exception e) {}
}while(true);
}
}
class ReentrantLockDemo {
public static void main(String args[]){
MyThread t1=new MyThread(“First Thread”);
MyThread t2=new MyThread(“Second Thread”);
t1.start();
t2.start();
}
}
 output:
First Thread --- got lock.
Second Thread --- unable to get lock and will try again.
Second Thread --- unable to get lock and will try again.
Second Thread --- unable to get lock and will try again.
Second Thread --- unable to get lock and will try again.
Second Thread --- unable to get lock and will try again.
First Thread --- releases the lock.
Second Thread ---got lock.
Second Thread --- releases lock.
Thread Pools (Executor FrameWork)
• Creating a new thread for every job may create
performance or memory problem. To overcome
of this we should go for ThreadPools.
• Thread Pool is a pool of already created threads
, ready to do out job.
• Java 1.5 version introduced thread pool
framework to implement ThreadPool.
• ThreadPool Framework is also known as
Executor Framework.
• We can create a thread pool as follows:
ExecutorService service=
Executors.newFixedThreadPool(5);
• We can submit a Runnable job by using submit()
method.
service.submit(job);
• We can shutdown executor service by using
shutdown() method
service.shutdown();
Example
import java.util.concurrent.*;
class PrintJob implements Runnable{
String name;
PrintJob(String name1){
name=name1;
}
public void run(){
System.out.println(name+” ---Job started by
Thread:“+Thread.currentThrad().getName());
try{
Thread.sleep(5000);
}
catch(Exception e){}
System.out.println(name+” ---Job completed by
Thread:“+Thread.currentThrad().getName());
}
}
class ExecuterDemo {
public static void main(String args[]){
PrintJob jobs[]={ new PrintJob(“Asheesh”),
new PrintJob(“Rishab”),
new PrintJob(“Rahul”),
new PrintJob(“Sumanth”),
new PrintJob(“Abinash”),
new PrintJob(“Amar”)};
ExecutorService service=
Executors.newFixedThreadPool(5);
for(PrintJob job:jobs){
service.submit(job);
}
service.shutdown();
}
}
• In the above example 3 threads are
responsible to execute 6 jobs, so that a single
thread can be reused for multiple jobs.
Note : While designing web servers and
application servers, we can use ThreadPool
concept.
Default ThreadPool size is 60 for most of
the servers.
Callable & Future
• In case of Runnable job , thread won’t return
anything after completing job.
• If a thread is required to return some result after
execution then we should go for Callable interface.
Callable interface contains only one method i.e.
call().
public Object call() throws Exception
• If we submit Callable object to executer then after
completing the job, thread returns an object of the
type Future i.e. Future object can be used to
retrieve the result from Callable job.
Example
import java.util.concurrent.*;
class MyCallable implements Callable{
int num;
MyCallable (int n){
num=n;
}
public Object call() throws Exception{
System.out.println( Thread.currentThrad().getName()+” is
responsible to find sum of first ”+num+” numbers”);
int sum=0;
for(int i=1;i<=num ; i++)
sum+=i;
return sum;
}
class CallableFutureDemo {
public static void main(String args[]){
MyCallable jobs[]={ new MyCallable(10),
new MyCallable(20),
new MyCallable(30),
new MyCallable(40),
new MyCallable(50),
new MyCallable(60)};
ExecutorService service= Executors.newFixedThreadPool(5);
for(PrintJob job:jobs){
Future f=service.submit(job);
System.out.println( f.get());
}
service.shutdown();
}
}
Difference between Runnable & Callable
1. If a thread not required to return 1. If a thread required to return
anything after completing the job , some thing after completing the
then we should go for Runnable. job , then we should go for Callable.
2. Runnable interface contains only 2. Callable interface contains only
one method i.e. run(). one method i.e. call().
3. Runnable job not required to 3. Callable job required to return
return any thing so run() method is any thing so call() method’s return
void. type is Future.
4. Within the run() method if there 4. Within the call() method if there
is any chance of raising checked is any chance of raising checked
exception, compulsory we should exception, we are not required to
handle by try, catch because we handle by try, catch because call()
cannot use throws keyword. method already throws Exception.
5. Runnable interface is present in 5. Callable interface is present in
java.lang package. java.util.concurrent package.
ThreadLocal class
• ThreadLocal class provides ThreadLocal variables.
• ThreadLocal class maintains values per thread basis.
• Each ThreadLocal object maintains a separate value ,
like userid, transactionid, etc.
• Thread can accesses its local value ,can manipulate
its value and even can remove its value.
• In every part of the code which is executed by the
thread , we can access its local variable.
• Example:
Consider a object which invokes some business
methods. We have a requirement to generate a unique
transaction id for each and every request and we have to
pass this transaction id to the business methods. For this
requirement we can use ThreadLocal to maintain a separate
transaction id for every request i.e. for every threads.
• Note:
1. ThreadLocal class introduced in 1.2 version and
enhanced in 1.5 version.
2. ThreadLocal can be associated with thread scope.
3. Total code which is executed by thread , has access to
the corresponding ThreadLocal variable.
4. A thread can access its own local variable and
cant access other thread’s local variable.
5. Once thread entered into dead state , all its local
variables are by default eligible for Garbage
Collector
Constructor:
ThreadLocal tl =new ThreadLocal();
creates a ThreadLocal variable
Methods:
1. Object get();
2. Object initialValue();
3. void set(Object newVal);

You might also like