Unit-11 Multithreaded Programming
Unit-11 Multithreaded Programming
programming
Unit :11
Content
● Thread priorities, synchronization, messaging, the thread class and the runnable interface
● Thread priorities
Example:
● While typing a java program in the editor we can able to listen mp3 audio songs at
the same time we can download a file from the net all these tasks are independent
of each other and executing simultaneously and hence it is Process based
multitasking.
● This type of multitasking is best suitable at "os level".
Thread based multitasking:
Note:
● The thread is in new state if you create an instance of Thread class but before the invocation of
start() method.
● When the thread instance is created, it will be in “New” state.
● The thread is in runnable state after invocation of start() method, but the thread scheduler has
not selected it to be the running thread.
● When the thread is started, it is called “Runnable” state.
Running State
● The thread is in running state if the thread scheduler has selected it.
● When the thread is running, it is called “Running” state
Waiting (Blocked) State
● This is the state when the thread is still alive, but is currently not eligible to run.
● When the thread is put on hold or it is waiting for the other thread to complete, then that state
will be known as “waiting” state.
● When a Java program starts up, one thread begins running immediately. This is
usually called the main thread of your program, because it is the one that is
executed when your program begins.
● The main thread is important for two reasons:
○ It is the thread from which other “child” threads will be spawned.
○ Often, it must be the last thread to finish execution because it performs various
shutdown actions.
The ways to define instantiate and start a new Thread:
System.out.println("Child thread");
}
class ThreadDemo{
public static void main(String[] args){
MyThread t=new MyThread();//Instantiation of a Thread
t.start();//starting of a Thread
for(int i=0;i<5;i++){ Executed by main thread
System.out.println("main thread");
}
}
}
Output
It varies.
Case 1:Thread Scheduler
● If multiple Threads are waiting to execute then which Thread will execute 1st is
decided by "Thread Scheduler" which is part of JVM.
Example:
start(){
● We can conclude that without executing Thread class start() method there is no
chance of starting a new Thread in java. Due to this start() is considered as heart of
multithreading.
Case 4: If we are not overriding run() method:
● If we are not overriding run() method then Thread class run() method will be
executed which has empty implementation and hence we won't get any output.
● It is highly recommended to override run() method. Otherwise don't go for
multithreading concept.
● Example:
Case 5: Overloading of run() method.
● We can overload run() method but Thread class start() method always invokes no argument run() method the
other overload run() methods we have to call explicitly then only it will be executed just like normal method.
Example
}
Case 6: overriding of start() method:
● If we override start() method then our start() method will be executed just like a
normal method call and no new Thread will be started.
● Example:
Note : It is never recommended to override start() method.
Case 7: Start method calling
Case 8: life cycle of the Thread:
● Once we created a Thread object then the Thread is said to be in new state or born
state.
● Once we call start() method then the Thread will be entered into Ready or Runnable
state.
● If Thread Scheduler allocates CPU then the Thread will be entered into running state.
● Once run() method completes then the Thread will entered into dead state.
Case 9:
● After starting a Thread we are not allowed to restart the same Thread once again
otherwise we will get runtime exception saying "IllegalThreadStateException".
Example:
t.start();//valid
;;;;;;;;
System.out.println(“Child Thread”);
}
class ThreadDemo{
public static void main(String[] args){
MyRunnable r=new MyRunnable();
Thread t=new Thread(r);//here r is a Target Runnable
t.start();
for(int i=0;i<10;i++){
System.out.println("main thread");
}
}
}
Output:
We can't expect exact output but there are several possible outputs.
Case study:
main thread
main thread
main thread
main thread
main thread
Case 2: t1.run():
● No new Thread will be created but Thread class run() method will be executed just
like a normal method call.
● Output:
main thread
main thread
main thread
main thread
main thread
Case 3: t2.start():
● New Thread will be created which is responsible for the execution of MyRunnable
run() method.
Case 4: t2.run():
● No new Thread will be created and MyRunnable run() method will be executed just
like a normal method call.
● Output:
● child Thread
● child Thread
● child Thread
● child Thread
● child Thread
● main thread
● main thread
● main thread
● main thread
● main thread
Case 5: r.start()
● We will get compile time error saying start()method is not available in MyRunnable
class.
Case 6: r.run():
● No new Thread will be created and MyRunnable class run() method will be executed
just like a normal method call.
Best approach to define a Thread
● Among the 2 ways of defining a Thread, implements Runnable approach is always
recommended.
● In the 1st approach our class should always extends Thread class there is no
chance of extending any other class hence we are missing the benefits of
inheritance.
● But in the 2nd approach while implementing Runnable interface we can extend
some other class also. Hence implements Runnable mechanism is recommended to
define a Thread.
Thread class constructors
Methods:
Note:
● The valid range of Thread priorities is 1 to 10[but not 0 to 10] where 1 is the least
priority and 10 is highest priority.
● Thread class defines the following constants to represent some standard priorities.
○ Thread. MIN_PRIORITY----------1
○ Thread. MAX_PRIORITY----------10
○ Thread. NORM_PRIORITY--------5
○ Thread.LOW_PRIORITY,
○ Thread.HIGH_PRIORITY
● Thread scheduler uses these priorities while allocating CPU.
● The Thread which is having highest priority will get chance for 1st execution.
● If 2 Threads having the same priority then we can't expect exact execution order it
depends on Thread scheduler whose behavior is vendor dependent.
● We can get and set the priority of a Thread by using the following methods.
● The allowed values are 1 to 10 otherwise we will get runtime exception saying
"IllegalArgumentException"
Default priority
● The default priority only for the main Thread is 5. But for all the remaining Threads the default priority will be
inheriting from parent to child. That is whatever the priority parent has by default the same priority will be for the
child also.
Example 1
class ThreadPriorityDemo{
System.out.println(Thread.currentThread().getPriority());//5
Thread.currentThread().setPriority(9);
System.out.println(t.getPriority());//9
}
Example 2
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); //----> 1
t.start();
for(int i=0;i<10;i++){
System.out.println("main thread");
}
}
}
● If we are commenting line 1 then both main and child Threads will have the same
priority and hence we can't expect exact execution order.
● If we are not commenting line 1 then child Thread has the priority 10 and main
Thread has the priority 5 hence child Thread will get chance for execution and after
completing child Thread main Thread will get the chance.
The Methods to Prevent a Thread from
Execution
We can prevent(stop) a Thread execution by using the following methods.
● yield();
● join();
● sleep();
yield():
● yield() method causes "to pause current executing Thread for giving the chance of
remaining waiting Threads of same priority".
● If all waiting Threads have the low priority or if there is no waiting Threads then the
same Thread will be continued its execution.
● If several waiting Threads with same priority available then we can't expect exact
which Thread will get chance for execution.
● The Thread which is yielded when it get chance once again for execution is depends
on mercy of the Thread scheduler.
Method
● If a Thread wants to wait until completing some other Thread then we should go for
join() method.
● Example: If a Thread t1 executes t2.join() then t1 should go for waiting state until
completing t2.
Diagram
t1 t2 t1.join t3 t2.join
Methods
If main thread calls join() on child thread object and child thread called join() on main
thread object then both threads will wait for each other forever and the program will be
hanged(like deadlock if a Thread class join() method on the same thread itself then the
program will be hanged ).
Sleep()
If a Thread don't want to perform any operation for a particular amount of time then we should go for sleep() method.
● If a method or block declared as the synchronized then at a time only one Thread is allow
to execute that method or block on the given object.
● But the main disadvantage of synchronized keyword is it increases waiting time of the
Thread and effects performance of the system.
● Every object in java has a unique lock. Whenever we are using synchronized keyword then
only lock concept will come into the picture.
● If a Thread wants to execute any synchronized method on the given object 1st it has
to get the lock of that object. Once a Thread got the lock of that object then it's allow
to execute any synchronized method on that object. If the synchronized method
execution completes then automatically Thread releases lock.
● While a Thread executing any synchronized method the remaining Threads are not
allowed execute any synchronized method on that object simultaneously. But
remaining Threads are allowed to execute any non-synchronized method
simultaneously. [lock concept is implemented based on object but not based on
method].
Example
class Display{
public synchronized void name(String name){
for(int i=0;i<5;i++){
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.name(name);
}
}
class SynchronizedDemo{
public static void main(String[] args){
Display d1=new Display();
MyThread t1=new MyThread(d1,"NCCS");
MyThread t2=new MyThread(d1,"College");
t1.start();
t2.start();
}
}
● If we are not declaring name() method as synchronized then both Threads will be
executed simultaneously and we will get irregular output.
● If we declare name()method as synchronized then the Threads will be executed one
by one that is until completing the 1st Thread the 2nd Thread will wait in this case
we will get regular output.
Case 1
Display d1=new Display();
t1.start();
t2.start();
● Even though we declared name() method as synchronized but we will get irregular
output in this case, because both Threads are operating on different objects.
Conclusion: If multiple threads are operating on multiple objects then there is no impact
of Syncronization.If multiple threads are operating on same java objects then syncronized
concept is required(applicable)
Synchronized block
● If very few lines of the code required synchronization then it's never recommended
to declare entire method as synchronized we have to enclose those few lines of the
code with in synchronized block.
Synchronized(this){
}
Example 2
Synchronized(b){
}
Inter Thread communication
● wait(),
● notify(),
● notifyAll()
● Two Threads can communicate with each other by using wait(), notify() and
notifyAll() methods.
● The Thread which is required updation it has to call wait() method on the required
object then immediately the Thread will entered into waiting state.
● After getting notification the waiting Thread will get those updations.
● wait(), notify() and notifyAll() methods are available in Object class but not in Thread
class because Thread can call these methods on any common object.
● To call wait(), notify() and notifyAll() methods compulsory the current Thread should
be owner of that object
○ i.e., current Thread should be in synchronized area. Hence we can call wait(),
○ notify() and notifyAll() methods only from synchronized area otherwise we will
get runtime exception saying IllegalMonitorStateException.
● Once a Thread calls wait() on the given object 1st it releases the lock of that object
immediately and entered into waiting state.
● Once a Thread calls notify() (or) notifyAll() methods it releases the lock of that
object but may not immediately.
● We can use notify() method to give notification for only one Thread. If multiple
Threads are waiting then only one Thread will get the chance and remaining Threads
has to wait for further notification. But which Thread will be notify(inform) we can't
expect exactly it depends on JVM.
● We can use notifyAll() method to give the notification for all waiting Threads. All
waiting Threads will be notified and will be executed one by one, because they are
required lock.
Note: On which object we are calling wait(), notify() and notifyAll() methods that
corresponding object lock we have to get but not other object locks.