11:THREADS



Thread is a function under execution. Normally Threads are used for multitasking.

Multitasking: - Concept o of executing more than one function at a time is known multitasking.
Multitasking came into picture to avoid the idle state of cpu.
IdleState of cpu :-  Suppose there are 3 functions in a class
class Example     {
void function1( )  {   }
void function2( )   {   }
void function3( )   {    }    
public static void main(String[] args)   {
Example e= new Example( );
e.function1( );
e.function2( );
e.function3( );    }   }










Explanation: 
·        In this example the functions are called one by one as above after completion of function1()  only function2() will be executed. After the successfully execution of function2() only function3 will be executed. That  means  function2() execution depends on the execution of function1(),and function3() execution depends on the execution of function2().
·        Suppose there are datatransfer statements as part of cpu, it is responsibility of a DMA to execute datatransfer  statements. So cpu will assign the task of datatransfer to DMA to eecute statements in funcion1()
·        Meanwhile the Processor(cpu) will remains idle.Thease state of cpu is known as “ Idle state of cpu ”.
·        Developers thinks that if we assign a some other task to cpu during idle state, we can improve the performance of cpu.This thought come here for birth of multitasking.
There are 2 types of multitasking
1.   Process based multitasking :- Concept of executing more than one programs simultaneous
belonging to different memory domain is known as “ process based multitasking “.Process is a program under execution.
2.   Thread based multitasking:- Concept of executing more than one functions simultaneously   
belonging to same memory domain is known as “ Thread based multitasking “(with in same program). Thread is a function under execution which is executing along with other functions.
To enable any function to be executed as a thread, we have to follow 2 conditions.
1.   Implement a thread functionality.
2.   Enable that implemented functionality to be executed as a thread functionality.
There are 2 ways to implement the thread functionality
1.   Extending a Thread  class.
2.   Implementing the Runnable Interface.
Whatever may be the approach we have to override a run() method. Overriding  run() is compalsary to achieve thread functionality.
Ex:   (Extending a thread class)
class ThreadA extends Thread     {
public void run()    {
System.out.println(“inside run() of threadA”); 
for (int i=0; i<=10; i++)    {
System.out.println(“the i  values are  : “+ i);   }   }
public static void main(String[] args)    {
ThreadA ta=new ThreadA();
ta.start();     }     }

Explanation :  To achieve a  thread functionality, we have to call a start() method available in thread class which will make run() available to the local operating system will be executed as a thread.
1st  Approach: 
Ex:   (executing three threads simultaneously)
class ThreadA extends Thread   {
public void method()  {
for(int i=0;i<50;i++)   {
System.out.println(“ThreadA method : ” +i );   }    }
public  void run()  {
method();  }   }
class ThreadB extends Thread   {
public  void run()  {
for(int x=50;x<100;x++)   {
System.out.println(“ThreadB  method :” +x);   }    }   }
class ThreadC extends Thread  {
public  void run()  {
for(int y=100;y<150;y++)  {
System.out.println(“ThreadB  method :” +y);   }    } 
public static void main(String[] args)  {
Thread A  ta=new ThreadA();
ta.start();
//ta.run();
ThreadB  ta=new ThreadB();
tb.start();
//tb.run();
ThreadC  ta=new ThreadC();
tc.start();
//tc.run();       }   }
Explanation: 
·        If we call a run() method directly ,run() will  be getting executing as normal function. If we call a start() method on any object, start() will hand over the run() of that object to the local operating system, which will be executed as a thread.
·        In the above program, we can’t expect the output of program.  Because all functions are threads here . They will  getting executed simultaneously(at a time) .
·        Scheduler will decide the time of each function execution, while the function is executing as a thread. Here functions will be executed independently.
·        To execute any functions as a threads, we have to call the functions from the run() method .
·        To define multiple threads, we have to define those many thread classes  as required.
·        From different run() methods of different  thread classes we have to call the required functions which we need to be executed as a threads. Because one thread class contains one run() only.
2nd Approach:
Ex:   ( Implementing Runnable  Interface )
class  MyThread  implements Runnable   {
void run()    {
 for(int z=0;z<5;z++)
 {   Syatem.out.println(“Mythread class” +z);     }   }
public static void main(String[] args)      {
MyThread mt=new MyThread();
Thread t=new Thread(mt);
t.start();   }   }
Explanation:  if our class is implementing a Runnable interface, then to enable class functions to be executed as a thread, we have to follow below 2 steps while calling methods.
1.   create object of our class (Runnabla obj) (Runnable r=new Implementaton())
2.   Create Thread class object  bypassing  Runnable object as a constructor , then call start() method on Thread class object.
(Q) How can we make one class object available to other class without extending ?
(A)   Using Parameterised  constructor.
(Q)  If our class is extending the another class, how can we implement the Thread functionality ?
(A)We have to use   “ implements Runnacle “to our class.
Ex: 

class A {
void functonA()  {
System.out.println(“funA of class A”);    }
class  MyThread extends A implements Runnable  {
void MyFunction()   {
for(int i=0;i<50;i++)   {
System.out.println(“  MyThread “);  }   }
public void run()  {
MyFunction();   }
public static void main(String[] args)   {
MyThread mt=new MyThread();
Thread t=new Thread(mt);
t.start();   }   }
We can suspend a thread based on 3 criterias
1.   Suspending a Thread based on time:-
There is a static method (sleep() ) available in Thread class, where we can suspend a thread for required amount of time .( public static native void sleep(long) throws InterruptedException )
This method accepts time in terms of milliseconds. This method is proven to generate checked exception (InterruptedException ).So we have to call this method always inside the try-catch block. Otherwise it will give as error.
2.   Suspending a Thread based on condition:
We have a join() method available in Thread class to suspend a  thread based on condition.
  final Synchronized void join()    throws  java.lang.InterruptedException.
Suppose if we have 3 threads t1,t2,t3. If we have condition that  run() of t3 should be executed only after  the values calculated from the run() of t1 . In this  situations, we have to call the join() method inside run() of  t3, which will enables  the  complete execution  of t1 thread before execution of t3 thread.
3.   Suspending a thread unconditionally:
We have a non-static  suspend() method available in Thread class, to suspend a thread unconditionally(without any condition). The suspended thread will not be reinitialised until and unless it is resumed ( resume() method available in  Thread class has called ). This methods are deprecated with current version of java(java 5.0). The alternative methods are wait(),notify() methods available in java.lang.Object class.
Ex:   (for sleep()method)

class Thread1 extends Thread  {
public void run()  {
System.out.println(“run method of Thread1”);
try   {
Thread.sleep(5*1000);
 }  catch(InterruptedException ie)
 {   ie.printStackTrace();   }
for(int a=0;a<20;<a++)    {
System.out.println(“  thread1 values are:   “+a);   }   }
public static void main(String[] args)  {
Thread1 t1=new Thread1();
t1.start();   }      }

Explanation:
1.    In this program, instead of handling the Exception in run() we can declare using throws. if we are declaring a run() with throws InterruptedException, then we are absolutely violating the concept of overriding.       
              [ public void run()throws InterruptedException  ]
2.   Concept of overriding  says that we have to define a same method with same signature in the sub class.
3.   main() method is also a thread. Here in the above program 2 threads are there (main(),Thread1 )
4.   So using a sleep() , we can suspend a thread based on time.
Ex:  ( for join() method )
class  ThreadA extends Thread  {
int sum;
public  void  run( )  {
for (int i=0;i<16;i++)  {
sum=sum+1;
System.out.println("Thread1  values: "+sum);  }   }   }
public  class Test {
public static void main(String[] args)  {      
ThreadA a=new ThreadA();
ThreadB b=new ThreadB();
ThreadC c=new ThreadC(a);
a.start();
c.start();   }    }

class ThreadB extends Thread   {
public  void  run()   {
for (int j=5;j<10;j++)   {
System.out.println("Thread1 j values: "+ j);   }    }   }
class ThreadC  extends  Thread   {
int res;
ThreadA  a;
ThreadC(ThreadA  a)  {
this.a=a;  }
public void run()  {
for (int k=10;k<20;k++)  {
if (k==15)  {
try  {
a.join();
}  catch (InterruptedException e)  {
System.out.println(e.getMessage());
}  //catch close 
res=a.sum-k;
System.out.println("result is :" +res);    }   }    }    }

Q) If a main() completes its execution first, then how remaining threads will be executed ?
A)  All the threads inside the main() is  “ default  joined “.
Thread  Safety:-
Concept of avoiding multiple threads acting upon the same function is known as  “Thread Safety ”  or “ Thread Synchronized “.
class Common  {
synchronized void function1(String s)  {
System.out.println(“hello”);
try  { Thread.sleep(3*1000);
}  catch(InterruptedException e)  {
e.printStackTrace();   }
System.out.println(“[“+s+”]world”);   }   }
class Thread1 extends Thread  {
Common c1;
Thread1(Common c1)  {
this.c1=c1;    }
public  void run()  {
c1.function1(“java”);  }  }
class Thread2 extends Thread  {
Common c1;
Thread2(Common c1)  {
this.c1=c1;    }
public  void run()  {
c1.function1(“c++”);  }  }
class Test  {
public static void main(String[] args)   {
Common c1=new Common();
Thread1 t1=new Thread1();
Thread2 t2=new Thread2();
t1.start();
t2.start();   }   }
Explanation: 
1.   In the above program, we have a class Common which has a function1()
2.   If we call this function1() ( without synchronized block ) from 2 threads  t1,t2  by passing inputs “Java”, ”c++”  thease will get the output as below.
OUTPUT:  hello hello [java]world
                    [c++]world
3.   Because 2 threads are acting upon the same function at the same time. So we are getting improper outputs which are not correct.
4.   If we use a synchronized keyword to define a function then only one thread can execute the entire function at a time.ie, we have provided the tread safety by  using synchronized keyword.
5.   Synchronization the process of avoiding the multiple threads acting upon the same function.
Differences b/w normal functions &  thread safety functions:
1.   Suppose, we have a function with 100 lines of statements, among 100 lines 4 lines has a user specific functionality. Thease  4 statements  should be different for  different users.
2.   Then we can provide the thread safety only for 4 statements using  synchronized keyword.
Syntax:  Function1() {
               //  statements
                Synchronized {
               // statements  } }
wait() :-   It is a method available in Object class. we can use a wait() method to suspend a thread until it      notified (  by using notify()  method ). Scheduler will schedule the time of execution of each thread normally. We can partially control the schedule processing using  wait() and notify().wait() should be called always inside the Synchronized block.
notify() :-  It is method available in Object class. We can use this method to resume the suspended  thread.
Ex:  
class Common  {
int value;
boolean  flag=true;
synchronized  void produce(int i)  {
this.value=i;
System.out.println(“producer prodused value” +i);
flag=false;
notify();
try  { 
wait();
}  catch(InterruptedException e)  { 
e.printStackTrace();   }   }
synchronized  int consume()  {
if(flag==true)   {
try  { 
wait();
}  catch(InterruptedException e)  { 
e.printStackTrace();   }   }
else  {
notify();
flag=false;   }
return value;  }  }
class  Producer extends Thread {
Common c;
Producer(Common c)  {
this.c=c;  }
public void run() {
int i=0;
while(true)  {
c.produce(i);
i++;
try {
Thread.sleep(1800);
} catch(InterruptedException e)  {
} } } }
class  Consumer extends Thread {
Common c;
Consumer(Common c)  {
this.c=c;  }
public void run() {
int j=0;
while(true)  {
j=c.cosume(j);
i++;
System.out.println(“consumer has consumed”);
try {
Thread.sleep(1800);
} catch(InterruptedException e)  {
} } } }
class Test {
public static void main(String[] args)  {
Common c=new Common();
Consumer cth=new Consumer(c);
Produser pth=new Produser(c);
cth.start();
Pth.start();  }  }


Explanation:
·        We cannot control the scheduling process of scheduler, but we can partially control the scheduling using wait() and notify() available in object class.
·        In the above program our requirement is
1.   producer will produce a value and producer, thread will wait till consumer will consume the       
produced value.
2.   Consumer  will consume a value produced and it will wait till the next value produced.
·        To do above task we have to establish the communication between two threads, that is producer has to communicate with consumer, and consumer has to communicate with producer, this process is known as “interthread  communication”.
·        We can achieve “interthread communication” using wait() and notify() methods.
Q. Why should we call notify() before wait() is called?.
Ans: Suppose there are two threads t1 and t2, if we are asking the t2 to wait and if t1 is already in wait state, then we con’t achieve anything. So if we call notify() method, if already some thread in wait() state that will be resumed back to initial state.
Properties of a thread:
·        If we have many threads which are in wait() state, when we notify() the threads, a thread which has highest priority will be notified first. The priority of main thread is “s”
·        Each thread will be assigned with a priority by the JVM.
·        If we want to assign a priority to our threads, we have a method setpriority() in thread class. t1.setpriority(6); this value lies between 0 to 9
0 is thread as the lower priority.
9 is thread as the higher priority.
DeadLock of Threads: 
It is the situation when the threads will lock forever because of circular dependency b/w two or more threads.
1.   Suppose, if we have two classes x, y with methods mone(), mtwo() which are synchronized.
2.   Suppose t1 is acting upon the mone() and t2 acting upon the mtwo().
3.   Both methods are synchronized methods.
4.   Now, if we call the  mtwo() from mone(), mtwo() will not  be executed. Because already t2 thread is acting upon the mtwo() and also two() is synchronized method .
5.   If we call the mone() from mtwo(), mone() method will not be executed. Because thread t1 is already acting upon the mone() and also tone() is synchronized method.
6.   So, these two methods will not be executed forever. This situation is known as “ DeadLock of threads ”. Here there is a circular dependency b/w two threads.
7.   DeadLock situation is a very dangerous in our application. Because it is performance hit on our application.
8.   suspend() , resume() methods were causes DeadLock situation. So thease two methods are deprecated from the current version.



Deamon Threads:-  A thread which is running in while loop, which starts its execution along with its parent thread and stops  execution along with its parent thread is known as “Deamon Thread”.
Ex:  Garbage Collector is a Deamon Thread.
Garbage Collector:-
1.   It is thread which is running in infinit loop (while loop).  It is starts  execution along with the main thread and stops execution when main thread stops.
2.   It is a background process which will run along with main thread to free the memory from the objects which are no long referenced (which are not used in the program).
3.   It is automatic process which will nullify the objects that are not used in the program.
4.   We can ask garbagecollector to garbagecollect the objects using  “ System.gc() “ method.
5.   When we call the gc() method, garbagecollector will accept that as just instruction. But it will not garbagecollect the object immedietly.
6.   It is an algorithm. It contains some process.
To convert  normal threads as Deomon threads :
Ex: 
class Deamon1 extends Thread  {
public  void run()  {
int i=0;
while(true) {
System.out.println(“Deamon1 thread  : : “ +i);
i++;   }  }
public static void main(String[] args)  {
Deamon1 dm=new Deamon1();
d.setDeamon(true);
d.start();
for(int i=50;i<=90;i++)  {
System.out.println(“parent  thread  : : “ +i);  }  }  }

Life Cycle of Threads:
1.   Thread will under go different changes during the life cycle of a thread.
2.   If, thread is running  we can say that thread is alive.
3.   When we start a thread it will go to ready to run state(runnable state).
4.   Based on scheduling times the requested threads will enter into the running state.
5.   We can suspend a thread using sleep(), wait(),suspend() methods
6.   Suspended threads can be resumed to go back to running state from where it has stoped.
7.   Finally, threads will completes its execution and it will be terminated, this is known as                                  
“ deadstate of thread “.
8.   Once the thread is terminated we can’t get back to running state.
9.   We have a method  isAlive()  o check whether the thread is alive or not.
This method returns “ true “, if the thread is alive
This method returns  “ false “, if the thread is not alive.
yield()  :-  If we have the threads with same priority, then we can stop the execution of the current thread tempararly using yield(). Using yield() method we can move thread from running state to runnable state.
                                                                    




No comments:

Post a Comment