THREADS
AND CONCURRENCY
Introduction
Multitasking Executing several tasks
simultaneously is called Multitasking’, There are 2 types of
multitasking.
1)
Process based Multitasking.
2) Thread
based Multitasking.
Process based Multi Tasking
Executing several tasks
simultaneously where each task is a separate independent process is called ‘Process
based Multitasking’.
Ex:While writing java program in the
editor we can run MP3 player. At the same time we can download a file
from the net. All these tasks are executing simultaneously and independent
of each other. Hence it is process based Multitasking. Process based Multitasking
is best suitable at O.S level.
Process based Multi Tasking
Executing several tasks
simultaneously where each task is a separate independent part of the same
program is called Thread based Multitasking. This type of multitasking is best
suitable
at programmatic level. Java provides
in built support for thread based multitasking by providing rich library
(Thread, ThreadGroup, Runnable ..etc) Whether it is Processbased or Threadbased
the main objective of multitasking is to reduce response time and improve
performance of the system. The main application area of multithreading is
videogames implementation, ,Multimedia graphics
…etc.
Defining Instantiating, Starting the
Thread
We can define instantiate and
starting a thread by using the following 2- ways.
1) By
extending Thread Class.
2) By
implementing Runnable interface.
By extending Thread Class
Ex:
class MyThread extends Thread
{
public
void run()
{
for
(int i=0; i<10 i="i" o:p="o:p">10>
{
System.out.println("Child
Thread");
}
}
}
class MultiThreadDemo
{
public
static void main(String[] args) throws InterruptedException
{
MyThread
t = new MyThread();
t.start();
for(int
i = 0; i<10 i="i" o:p="o:p">10>
{
System.out.println("Main
Thread");
}
}
}
Case1 :Thread Shedular:
If multiple threads are there then
which thread will get chance first for execution will be decided by “Thread
Scheduler”. Thread Scheduler is the post of JVM. The behavior of thread
scheduler is vendor dependent and hence we can’t expect exact O/P for the above
program.
The possible Outputs are:
(1) Child
(2) Main (3) Main
. . Child
. . Main
. . Child…………..
Case2:
The difference between t.start()
& t.run(): In
the case of t.start() a new thread will be created and which is responsible for
the execution
of run. But in the case of t.run()
no new thread will be created and run() method will be executed just like a
normal method by the main thread. Hence in the above program if we are
replacing t.start() with t.run() then the O/P is
Child
Child
Child
Child
.
.
.
.
Case3:
Importance of Thread Class start()
method: After
Creating thread object compulsory we should perform registration with the
thread
Main scheduler. This will take care
by start() of Thread class, So that the programmers has to concentrate on only
job. With out executing Thread class start() method there is no chance of start
a new Thread in java.
start()
{
Register
our thread with the thread scheduler. Invoke run method.
}
Case4:
If we are not overriding run()
method:Then the
thread class run method will be executed which has empty implementation.
Ex:
class MyThread extends Thread
{
}
class ThreadDemo
{
public
static void main(String arg[])
{
MyThread
t = new MyThread();
t.start();
}
}
O/P:- no output
Case5:
If we are overriding start() method:
Ex:
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 arg[])
{
MyThread
t = new MyThread();
t.start();
}
}
O/P:- start() method In this case start()
method will be executed just like a normal method.
Case6:
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 arg[])
{
MyThread
t = new MyThread();
t.start();
System.out.println("main
method");
}
}
O/P:- start() method.
run
method.
main
method.
Life cycle of Thread
When u write new MyThread()
Note:- we can’t stop a running Thread
explicitly. But until 1.2 version we can achieve this by using stop() method
but it is deprecated method. Similarly suspend() and resume() methods also deprecated.
After starting a thread we are not
allowed to restart the same thread once again, violation leads to Runtime Error
saying “IllegalThreadStateException”.
MyThread
t = new MyThread();
t.start();
t.start();
àIllegal Thread state Exception.
By Implementing Runnable Interface
We can define a Thread by
implementing runnable interface also. Runnable interface available in java.lang
package and contains only one method
public
void run();
Ex:
class MyRunnable implements Runnable
{
public
void run()
{
for(int
i = 0;i<=10;i++)
{
System.out.println("Child
Thread");
}
}
}
class ThreadDemo
{
public
static void main(String arg[])
{
MyRunnable
r = new MyRunnable();
Thread
t = new Thread(r);
t.start();
for(int
i = 0;i<=10;i++)
{
System.out.println("Main
Thread");
}
}
}
Possible O/P:
Main
Thread
Child
Thread
Main
Thread
Child
Thread
Main
Thread
Child
Thread
Main
Thread
Child
Thread
Ex:
MyRunnable
r = new MyRunnable();
Thread t1
= new Thread();
Thread t2
= new Thread(r);
Case1:
t1.start();
A new thread will be started and
executes thread class run method(Which is having empty
implementation).
Case2:
t1.run();
No new thread will be created and
thread class run() method will be executed just like a normal method call.
Case3:
t2.start();
A new thread will be created and
responsible for execution of MyRunnable run method.
Case4:
t2.run();
No new thread will be created and
MyRunnable run method will be executed just like a normal method call.
Case5:
r.run();
No new thread will be created and
MyRunnable run method will be executed just like a normal method call.
Case6:
r.start();
Compiler Error: MyRunnable doesn’t
contain start method.
In which of the following cases a
new thread will be started.
1) t1.start(); |/
2) t1.start(); |/
3) r.start();
4) t1.run();
5) t2.run();
6) r.run();
Note:- Among 2- approaches of defining a
thread – implements Runnable is always recommended to use in the 1st approach
as we are already extending thread class. There is no chance of extending any other
class. Hence we are missing the key benefits of oops inheritance(reusability) .
hence this approach is not recommended to use.
Hybrid Mechanism To define a
thread(not recommended to use)
Ex:
class MyThread extends Thread
{
public
void run()
{
System.out.println("Child Thread");
}
}
class HybridThreadDemo
{
public
static void main(String arg[])
{
MyThread
t1 = new MyThread();
Thread
t = new Thread(t1);
t.start();
System.out.println("Main
Thread");
}
}
O/P:- Child Thread
Main
Thread
Or
Main
Thread
Child
Thread
Thread class construtors
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(ThreadGroup
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 stacksize);
setting and getting the name of a Thread
Thread class defines the following
methods to set and get the name of a Thread.
1) public
final void setName(String name);
2) public
final String getName();
Ex:
class Test
{
public
static void main(String arg[])
{
System.out.println(Thread.currentThread().getName());
Thread.currentThread().setName("New
Thread");
System.out.println(Thread.currentThread().getName());
}
}
O/P:-main
New
Thread
Thread Priorities
Every Thread in java having some
priority. The range of valid thread priorities is (1-10) (1 is least & 10
is Highest). Thread class defines the following constant for representing some
standard priorities.
Thread.MIN_PRIORITY
1
Thread.NORM_PRIORITY
2
Thread.MAX_PRIORITY
3
Thread scheduler use these
priorities while allocating C.P.U. The Thread which is having highest priority will
get chance first for execution. If two threads having the same priority then
which thread will get chance first for execution is decided by Thread
Scheduler, which is vendor dependent i.e we can’t expect exactly. The default
priority for the main thread only the 5, but for all the remaining threads the
priority will be inherit from parent i.e what ever the parent has the same
priority the child thread also will get. Thread class contains the following
methods to set and get priorities of thread.
1)
public
final void setPriority(int priority) where priority should be from 1-10 other
wise R.E: IllegalArgumentException. 2) public final int getPriority();
Ex:
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 arg[])
{
MyThread
t = new MyThread();
System.out.println(t.getPriority());
t.setPriority(10);
t.start();
for(int
i =0;i<10 i="i" o:p="o:p">10>
{
System.out.println("Main
Thread");
}
}
}
O/P:-Main Thread
Child
Thread
Main
Thread
Child
Thread
Main
Thread
Child
Thread
Main
Thread
Child
Thread
Some Operating Systems may not
provide support for thread priorities.
Preventing Thread from execution
We can prevent a thread from
execution by using the following methods.
1)
yield()
2)
join()
3)
sleep()
yield()
The thread which is called yield()
method temporarily pause the execution to give the chance for remaining
threads of same priority. If there is no waiting thread or all waiting threads
having low priority. Then the same thread will get the chance immediately for
the execution. public static native void yield();
Ex:
class MyThread extends Thread
{
public
void run()
{
for
(int i=0; i< 10 ; i++ )
{
System.out.println("Child
Thread");
Thread.yield();
}
}
}
class YieldDemo
{
public
static void main(String arg[])
{
MyThread
t = new MyThread();
t.start();
for(int
i =0;i<10 i="i" o:p="o:p">10>
{
System.out.println("Main
Thread");
}
}
}
In this case main thread will get
chance more no of times for execution. Because child thread intentionally
calling “yield()” method. As the yield method is native method some
Operating system may not provide the support for this.
join()
If a thread wants to wait until some
other thread completion then we should go for join method.
Ex:If a thread t1 executes
t2.join(), then t1 will be entered into waiting state until t2 completion.
public final void join() throws
InterruptedException
public final void join(long ms)
throws InterruptedException
public final void join(long ms, int
ns) throws InterruptedException
Ex:
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 JoinDemo
{
public
static void main(String arg[])throws InterruptedException
{
MyThread
t = new MyThread();
t.start();
t.join();
à 1
//t.join(4000)
for(int
i =0;i<10 i="i" o:p="o:p">10>
{
System.out.println("Main
Thread");
}
}
}
O/P:-
Child
Thread Child
Thread
Child
Thread Child
Thread
Child
Thread Child
Thread
Child
Thread Main Thread
Child
Thread Main Thread
t.join()à Child Thread t.join(4000)à Main Thread
Main
Thread Main
Thread
Main
Thread Child
Thread
Main
Thread Main
Thread
Main
Thread Main
Thread
Main
Thread Main
Thread
Main
Thread Child
Thread
Main
Thread Child
Thread
Main
Thread Child
Thread
Main
Thread Child
Thread
sleep()
If a method has to wait some
predefined amount of time with out execution then we should go for sleep()
method.
public static void sleep(long
ms)throws InterruptedException
public static void sleep(long m, int
m)throws InterruptedException
Ex:
class MyThread extends Thread
{
public
void run()
{
try
{
for
(int i = 0;i<10 i="i" o:p="o:p">10>
{
System.out.println("This
is Lazy Method");
Thread.sleep(1000);
}
}
catch
(InterruptedException e)
{
System.out.println(e);
}
}
}
class SleepDemo
{
public
static void main(String arg[])throws InterruptedException
{
MyThread
t = new MyThread();
t.start();
System.out.println("Main
Thread");
}
}
O/P:- Main Thread
This is Lazy Method
This is Lazy Method
This is Lazy Method
This is Lazy Method
This is Lazy Method
interrupting a thread
we can interrupt a sleeping or
waiting thread by using interrupt method of thread class.
public
void interrupt()
when ever we are calling interrupt()
the target thread may not be effected immediately. At the time of calling
interrupt if the target thread is not in sleeping or in waiting state interrupt
call will wait
until target thread entered into
sleeping or waiting state.
Ex:
class MyThread extends Thread
{
public
void run()
{
try
{
for
(int i = 0;i<10 i="i" o:p="o:p">10>
{
System.out.println("This
is Lazy Method");
//
Thread.sleep(3000); 1
}
Thread.sleep(3000);
2
}
catch
(InterruptedException e)
{
System.out.println(e);
}
}
}
class InterruptDemo
{
public
static void main(String arg[])throws InterruptedException
{
MyThread
t = new MyThread();
t.start();
t.interrupt();
System.out.println("Main
Thread");
}
}
O/P:-
Sleep() used inside for loop à This is Lazy Method
Main Mehod
Java.lang.InteruptedException:sleep
interrupted
Main
Thread
This
is Lazy Method
This
is Lazy Method
This
is Lazy Method
Sleep() used outside for loopà This is Lazy Method
This
is Lazy Method
This
is Lazy Method
This
is Lazy Method
Java.lang.InteruptedException:sleep
interrupted
Synchronization table for yield(),
join() & sleep()
Property
|
yield()
|
join()
|
sleep()
|
Is it overloaded?
|
No
|
Yes
|
Yes
|
Is it static?
|
Yes
|
No
|
Yes
|
Is it final?
|
No
|
Yes
|
No
|
Is it throws
InterruptedException?
|
No
|
Yes
|
Yes
|
Is it native?
|
Yes
|
No
|
Sleep(long ms)ànative
Sleep(long ms, int ms)ànot native
|
Synchronization
‘synchronized’ is the keyword
applicable for the methods and blocks. We can’t apply this
keyword for variables and classes. If a method declared as
synchronized at a time only one thread is allowed to execute that method on the
given object. The main advantage of synchronized keyword is we can overcome
data inconsistency problem. The main limitation of synchronized keyword is it
may create preference problems. Hence if there is no specific requirement it’s
not recommended to use synchronized keyword. Every object in java has a unique
lock. When ever are using synchronized keyword then object level lock concept
will come into picture. If a thread want to execute any synchronized method on
the object first it should require the lock of that object. Once a thread got
the lock then it is allowed to execute any synchronized method on that object.
While a thread executing a
synchronized method on the object, then the remaining threads are not allowed
to execute any synchronized method on the same object. But the remaining
threads are allowed to execute any non-synchronized method on the same object. Every
object in java has unique lock but a thread can acquire more than one lock at a
time.
Ex:
class Display
{
public
synchronized void wish(String name)
{
for(int
i =0;i<10 i="i" o:p="o:p">10>
{
System.out.print("Hai.......!");
try
{
Thread.sleep(2000);
}
catch
(InterruptedException e)
{
}
System.out.println(name);
}
}
}
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 arg[])
{
Display
d = new Display();
MyThread
t1 = new MyThread(d,"YS");
MyThread
t2 = new MyThread(d,"Babu");
t1.start();
t2.start();
}
}
O/P:-
Hai………..!YS
Hai………..!YS
Hai………..!YS
Hai………..!YS
Hai………..!YS
Hai………..!Babu
Hai………..!Babu
Hai………..!Babu
Hai………..!Babu
Hai………..!Babu
Hai………..!Babu
If we are not declaring wish method
as “synchronized” we will get irregular o/p because both threads will execute
simultaneously. If we are declaring wish method as synchronized we will get
regular o/p because at a time only one thread is allowed to execute wish
method.
Display
d1 = new Display();
Display
d2 = new Display();
MyThread
t1 = new MyThread(d1,"YS");
MyThread
t2 = new MyThread(d2,"Babu");
t1.start();
t2.start();
O/P:-
Hai………..!Hai………!YS
Babu
Hai………..!Hai………!YS
Babu
Hai………..!Hai………!YS
Hai………..!Babu
Hai………..!YS
Hai………..!Babu
Hai………..!YS
Hai………..!Babu
Hai………..!YS
Babu
Even though wish method is
synchronized we will get irregular o/p only because both threads are operating on
different objects.
Class level lock: If a thread want to execute any
static synchronized method then compulsory that thread should require class
level lock. While a thread executing any static system method then the remaining
threads are not allowed to execute any static synchronized method of the same
class simultaneously. But the remaining threads are allowed to execute any
non-synchronized static methods, synchronized – instance method, non –
synchronized instance method simultaneously. Declare static synchronized in
display method and try the above example we will get regular p/p because
there is class level lock.
Synchronized Blocks
It is not recommended to declare
entire method as synchronized if very few lines of code causes the problem that
code we can declare inside Synchronized Block so that we can improve
performance of
the system.
Syntax:
synchronized(b)
{
//critical
section.
}
Where ‘b’ is an object reference. To
get the lock for the current object we can define synchronized block as follows
synchronized(this)
{
//critical
section.
}
We can define synchronized block to
get class level as follows
synchronized(Display.class) we can
define synchronized block either for object references or for class
references But not for primitives violation leads to Compile time error.
int i =10;
synchronized(i)
{
//------
}
C.E:- unexpected type
found : int.
required : reference.
Synchronized statement(Only for
Interview Purpose):
The statement which are defined in
inside synchronized method or synchronized blocks are called ‘synchronized
statement’.
Inter Thread Communication
Two threads can communicate with each
other by using wait(), notify(), notifyAll(). These methods are available in
object class but not in thread class. Because threads are calling these
methods on any object.
We should call these methods only
from synchronized area other wise we get runtime exception saying IllegalMonitorStateException.
If a thread executes wait() method
it immediately releases the lock of that object(But not all locks) and entered
into waiting state.
After giving the notification also
the thread releases the lock but may not be immediately.
public final void wait() throws
InterruptedException
public final void wait(long ms)
throws InterruptedException
public final void wait(long ms, int
ns) throws InterruptedException
public final void notify();
public final void notifyAll();
Method Is lock released
yield() X
join() X
sleep() X
wait() |/
notify() |/
notifyall() |/
Ex:
class ThreadA
{
public
static void main(String arg[])throws InterruptedException
{
ThreadB
b = new ThreadB();
b.start();
System.out.println("Main
Method");
Thread.sleep(100);
------------------- 1
System.out.println(b.total);
}
}
class ThreadB extends Thread
{
int total
= 0;
public
void run()
{
System.out.println("Child
Starting calculation");
for(int
i = 1; i<=100; i++)
{
if(i
== 1)System.out.println("in for loop ");
total
= total + i;
}
}
}
O/P:-
Main Method Main Method
Using sleepàChild starting calculation
without usingà Child starting calculation 0
In
for loop in
for loop
5050
Here we used sleep() method to give
chance to child thread. But we can’t say child thread will finish his work with
in given time. So we may get unusually outputs. There is no Guaranteed Output.
Ex:
class ThreadA
{
public
static void main(String arg[])throws InterruptedException
{
ThreadB
b = new ThreadB();
b.start();
synchronized(b)
{
System.out.println("Main
Method calling wait method ");
b.wait();
System.out.println("Main Got Notification");
System.out.println(b.total);
}
}
}
class ThreadB extends Thread
{
int total
= 0;
public
void run()
{
synchronized(this)
{
System.out.println("Child
Starting calculation");
for(int
i = 1; i<=100; i++)
{
total
= total + i;
}
System.out.println("Child
giving notification");
this.notify();
}
}
}
O/P:- Main Method calling wait
method
Child
starting calculation
Child
giving notification
5050
Dead Lock
If two threads are waiting for each
other forever, then the threads are said to be in “deadlock”. There is
no deadlock resolution technique but prevention technique are available
Ex:
Banker’s Algorithm.
Ex:
class A
{
synchronized
void foo(B b)
{
System.out.println("Threas
1 entered foo() method");
Using
sleep() With out using
try
{
Thread.sleep(600);
}
catch
(InterruptedException e)
{
}
System.out.println("Thread
1 is trying to call b.last()");
b.last();
}
synchronized
void last()
{
System.out.println("Inside
A, This is last() method");
}
}
class B
{
synchronized
void bar(A a)
{
System.out.println("Threas
2 entered bar() method");
try
{
Thread.sleep(600);
}
catch
(InterruptedException e)
{
}
System.out.println("Thread
2 is trying to call b.last()");
a.last();
}
synchronized
void last()
{
System.out.println("Inside
B, This is last() method");
}
}
class DeadLock implements Runnable
{
A a = new
A();
B b = new
B();
DeadLock()
{
Thread
t = new Thread(this);
t.start();
b.bar(a);
}
public
void run()
{
a.foo(b);
}
public
static void main(String arg[])
{
new DeadLock();
}
}
O/P:-
There are 2 entered bar() method
Thread 1 entered foo() method
Thread 2 trying to call b.last()
Thread 1 is trying to call b.last()
DaemonThread
The threads which hare running in
the background to provide support for user defined threads are called “Daemon Thread”. Usually daemon thread
are running with low priority but based on our requirement we can
increase their priority also.
We can check whether the given
thread is daemon or not by using the following thread class thread.
public
boolean isDaemon()
we can change the daemon nature of a
thread by using setDaemon() method of thread class.
public
void setDaemon(Boolean b)
the daemon nature of a thread is inheriting
from the parent. i.e if the parent is daemon then the child is also daemon
and if the parent is non – daemon then the child is also non – daemon.
After starting a thread we are not
allowed to change the daemon nature violation leads to runtime exception saying
IllegalThreadStateException.
Ex:
class MyThread extends Thread
{
}
class Test
{
public
static void main(String arg[])
{
System.out.println(Thread.currentThread().isDaemon());
MyThread
t = new MyThread();
System.out.println(t.isDaemon());
t.setDaemon(true);
System.out.println(t.isDaemon());
t.start();
//t.setDaemon(false);
1
}
}
O/P:-false
False
If we don’t comment line 1 we will
get the IlleagalThreadStateException, see the following o/p.
False
False
True
Exception in thread “main” java.lang.
IlleagalThreadStateException,
at java.lang.Thread.setDemon(Unkonw
source)
at
Test.main(ThreadDemo.java:416)
We can’t change the daemon nature of
main thread because it has started already before main() method only. All the
daemon threads will be terminated automatically when ever last non – daemon thread
terminates.
Ex:
class MyThread extends Thread
{
public
void run()
{
for(int
i = 0;i<10 i="i" o:p="o:p">10>
{
System.out.println("Child
Thread");
try
{
Thread.sleep(1000);
}
catch
(InterruptedException e)
{
}
}
}
}
class DaemonThreadDemo
{
public
static void main(String arg[])
{
MyThread
t = new MyThread();
t.setDaemon(true);
1
t.start();
System.out.println("The
end of main");
}
}
O/P:-
Child Thread
The end of main
If we are commenting line 1, then
both child and main threads are non – Daemon, hence they will execute until
their completion.
If we are not commenting line 1,
then the child thread is daemon and hence it will terminate automatically when
ever main() thread terminates.
No comments:
Post a Comment