Monday, June 30, 2014

MultiThreading

Many multithreading needs are related to building responsive user interfaces. For example, most word processing applications contain an “autosave” function. You can configure the word processor to save your documents every xminutes. 

The autosave executes automatically on schedule without needing your intervention. A save may take several seconds to execute, yet you can continue work without interruption.

The word processor code manages at least two threads. One thread, often referred to as the foreground thread, is managing your direct interaction with the word processor. Any typing, for example, is captured by code executing in the foreground thread. Meanwhile, a second, background thread is checking the clock from time to time. Once the configured number of minutes has elapsed, the second thread executes the code in the save function.

On a multiple-processor machine, multiple threads can actually run simultaneously, each thread on a separate processor. On a single-processor machine, threads each get a little slice of time from the processor (which can usually only execute one thing at a time), making the threads appear to execute simultaneously.

The challenge is when multiple threads need to share the same resource. If you are not careful, multithreaded solutions can generate incorrect answers or freeze up your application.

Creating and Running Threads

A thread is a lightweight subprocess, a smallest unit of processing. It is a separate path of execution. It shares the memory area of process.
  • Note: At least one process is required for each thread.
  • Threads share the same address space.
  • Thread is lightweight.
  • Cost of communication between the thread is low.
Threads share a common memory area. They don't allocate separate memory area so save memory, and context-switching between the threads takes less time than processes.

Life Cycle of a thread:

The life cycle of the thread is controlled by JVM. The thread states are as follows:
  1. New
    • A thread is in New state, if you create an instance of Thread class but before the invocation of start() method.
  2. Runnable
    • The thread is in Runnable state after invocation of start() method, but the thread scheduler has not selected it to be the running thread.
  3. Running
    • The thread is in Running state if the thread scheduler has selected it.
  4. Non-Runnable (Blocked)
    • This is the state when the thread is still alive, but is currently not eligible to run.
  5. Terminated
    • A thread is in Terminated or dead state when its run() method exits.



2 ways to create Threads in Java:

Java supplies two ways for you to initiate a separate thread.

The first requires you to extend the class java.lang.Thread and provide an implementation for the run method. Subsequently, you can call the start method to kick things off. At that point, code in the run method begins execution in a separate thread.


A second technique for spawning threads is to create an instance of a class that implements the interface java.lang.Runnable:
public interface Runnable {
   public void run();
}
You then construct a Thread object, passing the Runnable object as a parameter. Sending the message start to the Thread object initiates code in the run method. This second technique is often done using anonymous inner class implementations of Runnable.

A Thread is an object that manages information about a thread of execution(control flow that the thread scheduler manages).

start() method of Thread class is used to start a newly created thread. It performs following tasks:
  • A new thread starts with new callstack.
  • The thread moves from New state to the Runnable state.
  • When the thread gets a chance to execute, its target run() method will run.
Thread class itself implements the Runnable interface. If you extend Thread, you will need to override the run method in order for anything useful to happen.

Example: Creating threads by extending 'Thread' class.
First Thread:

//This class is made as a thread by extending "Thread" class.
public class FirstThread extends Thread 
{ 
  //This method will be executed when this thread is executed 
  public void run() 
  { 
    //Looping from 1 to 10 to display numbers from 1 to 10 
     for (int i=1; i<=10; i++) 
     { 
        //Displaying the numbers from this thread 
        System.out.println( "Messag from First Thread : " +i);      
        /*taking a delay of one second before displaying next number
        * 
        * "Thread.sleep(1000);" - when this  statement is executed, 
        * this thread will sleep for 1000  milliseconds (1 second) 
        * before executing the next statement. 
        * 
        * Since  we are making this thread to sleep for one second, 
        * we need to handle  "InterruptedException". Our thread 
        * may throw this exception if it is  interrupted while it 
        * is sleeping. 
        * 
        */ 

        try 
        { 
           Thread.sleep(1000); 
        } 
        catch (InterruptedException  interruptedException) 
        { 
          /*Interrupted exception will be thrown when a sleeping  
          * or waiting thread is interrupted. 
          */ 
          System.out.println( 
              "First Thread is interrupted when it is  sleeping"  
                          +interruptedException); 
        } 
      } 
   } 
} 
Second Thread: 
//This class is made as a thread by extending "Thread" class.  
public class SecondThread extends Thread 
{   
  //This method will be executed when this thread is executed   
  public void run()     
  {             
    //Looping from 1 to 10 to display numbers from 1 to 10      
    for (int i=1; i<=10; i++)        
    {           
       System.out.println( "Messag from Second Thread : " +i);                 
       /*taking a delay of one second before displaying next number 
       * "Thread.sleep(1000);" - when this statement is executed, 
       * this thread will sleep for 1000 milliseconds (1 second) 
       * before executing the next statement.             
       *              
       * Since we are making this thread to sleep for one second, 
       * we need to handle "InterruptedException". Our thread 
       * may throw this exception if it is interrupted while it 
       * is sleeping.             
       */           
       try          
       { 
           Thread.sleep (1000);          
       }            
       catch (InterruptedException interruptedException)            
       {                
          /*Interrupted exception will be thrown when a sleeping 
           * or waiting thread is interrupted.               
           */               
           System.out.println( 
                      "Second Thread is interrupted when it is sleeping"  
                           +interruptedException);           
       }        
    }   
  } 
}
Main Class: 
public class ThreadDemo 
{      
  public static void main(String args[])    
  {           
    //Creating an object of the first thread 
    FirstThread   firstThread = new FirstThread();              

    //Creating an object of the Second thread       
    SecondThread   secondThread = new SecondThread();            

    //Starting the first thread         
    firstThread.start();                
    //Starting the second thread        
    secondThread.start();   
  } 
}
Example: Creating threads using 'Runnable' interface. 
First thread:
// This class is made as a thread by implementing 
// "Runnable" interface. 
public class FirstThread implements Runnable 
{  
  //This method will be executed when this thread is executed   
  public void run()     
  {                 
    //Looping from 1 to 10 to display numbers from 1 to 10      
    for ( int i=1; i<=10; i++)       
    {           
        //Displaying the numbers from this thread
     System.out.println( "Messag from First Thread : " +i);  
       /*taking a delay of one sec before displaying next number
        *          
        * "Thread.sleep(1000);" - when this statement is executed,
        * this thread will sleep for 1000 milliseconds (1 second) 
        * before executing the next statement. 
        *    
        * Since we are making this thread to sleep for one second,
        * we need to handle "InterruptedException". Our thread 
        * may throw this exception if it is interrupted while it  
        * is sleeping. 
        *     
        */   
        try         
        {           
           Thread.sleep (1000);             
        }           
        catch (InterruptedException interruptedException)           
        {   
           /*Interrupted exception will be thrown when a sleeping 
            *or waiting thread is interrupted.   
            */      
            System.out.println( "First Thread is interrupted when it is sleeping" +interruptedException);           
        }   
    }   
  } 
}
Second thread:
//This class is made as a thread by implementing "Runnable" interface. 
public class SecondThread implements Runnable 
{   
   //This method will be executed when this thread is executed  
   public void run()    
   {            
      //Looping from 1 to 10 to display numbers from 1 to 10        
      for ( int i=1; i<=10; i++)         
      {             
  System.out.println( "Messag from Second Thread : " +i); 
        /*taking a delay of one sec before displaying next number 
         * 
         * "Thread.sleep(1000);" - when this stmt is executed,     
         * this thread will sleep for 1000 milliseconds (1 second)  
         * before executing the next statement.    
         *   
         * Since v r making this thread to sleep for one second, 
         * we need to handle "InterruptedException". Our thread 
         * may throw this exception if it is interrupted while it
         * is sleeping.  
         */             
         try            
         {              
             Thread.sleep(1000);            
         }          
         catch (InterruptedException interruptedException)          
         {              
            /*Interrupted exception will be thrown when a sleeping 
             *or waiting thread is interrupted. 
             */    
             System.out.println( "Second Thread is interrupted when it is sleeping" +interruptedException); 
         }      
      }     
    }  
}
Main class:
public class ThreadDemo 
{ 
     public static void main(String args[]) 
     { 
        //Creating an object of the first thread 
        FirstThread   firstThread = new FirstThread(); 
        //Creating an object of the Second thread 
        SecondThread   secondThread = new SecondThread(); 
        //Starting the first thread 
        Thread thread1 = new Thread(firstThread); 

        thread1.start(); 
        //Starting the second thread 
        Thread thread2 = new Thread(secondThread); 
        thread2.start(); 
     } 
}
Question: Can we start a thread twice??
No. After starting a thread, it can never be started again. If you do so, an IllegalThreadStateException is thrown.
Question: What if we call run() method directly instead start() method?
Invoking the run() method from main thread, the run() method goes onto the current call stack rather than at the beginning of a new call stack. There is no context-switching.
 Cooperative and Preemptive Multitasking

In a single-processor environment, individual threads each get a slice of time from the processor in which to execute. The question is, how much time does each thread get before another thread takes over? The answer depends upon many things, including which operating system you are using to run Java and your particular JVM implementation.

Most modern operating systems (including Unix variants and Windows) use preemptive multitasking, in which the operating system (OS) interrupts the currently executing thread. Information about the thread is stored, and the OS goes on to provide a slice of time to the next thread. In this environment, all threads will eventually get some attention from the thread scheduler.

The other possibility is that the operating system manages threads using cooperative multitasking. Cooperative multitasking depends on thread code behaving well by yielding time to other threads frequently. In a cooperative threading model, one poorly written thread could hog the processor completely, preventing all other threads from doing any processing. Threads may yield time by explicitly calling the yield method, by sleeping, when blocking (waiting) on IO operations, and when they are suspended, to mention a few ways.
            Thread.yield();

currentThread() method
The currentThread() method returns a reference to the currently executing thread object.
  1. class MultiThreads extends Thread{  
  2.  public void run(){  
  3.   System.out.println(Thread.currentThread().getName());  
  4.  }  
  5.  }  
  6.  public static void main(String args[]){  
  7.   MultiThreads t1=new MultiThreads();  
  8.   MultiThreads t2=new MultiThreads();  
  9.   
  10.   t1.start();  
  11.   t2.start();  
  12.  }  
  13. }  
The Join() method
The join() method waits for a thread to die. In other words, it causes the currently running threads to stop executing until the thread it joins with completes its task.

public void join()throws InterruptedExceptionpublic void join(long milliseconds)throws InterruptedException

  1. class Multi extends Thread{  
  2.  public void run(){  
  3.   for(int i=1;i<=5;i++){  
  4.    try{  
  5.     Thread.sleep(500);  
  6.    }catch(Exception e){System.out.println(e);}  
  7.   System.out.println(i);  
  8.   }  
  9.  }  
  10. public static void main(String args[]){  
  11.  Multi t1=new Multi();  
  12.  Multi t2=new Multi();  
  13.  Multi t3=new Multi();  
  14.  t1.start();  
  15.  try{  
  16.   t1.join();  
  17.  }
  18. catch(Exception e){System.out.println(e);}  
  19.   
  20.  t2.start();  
  21.  t3.start();  
  22.  }  
  23. }  

o/p: You can see, when t1 completes its task then t2 and t3 starts executing.
       1
       2
       3
       4
       5
       1
       1
       2
       2
       3
       3
       4
       4
       5
       5
The Thread class provides methods to change and get the name of a thread.
  1. public String getName(): is used to return the name of a thread.
  2. public void setName(String name): is used to change the name of a thread.
Examples:
t1.getName();t1.setName("Sonoo Jaiswal");
Priority of a Thread
Each thread have a priority. Priorities are represented by a number between 1 and 10. In most cases, thread scheduler schedules the threads according to their priority (known as preemptive scheduling). But it is not guaranteed because it depends on JVM specification that which scheduling it chooses.
  1. public static int MIN_PRIORITY
  2. public static int NORM_PRIORITY
  3. public static int MAX_PRIORITY
Default priority of a thread is 5 (NORM_PRIORITY). The value of MIN_PRIORITY is 1 and the value of MAX_PRIORITY is 10.
  1. m1.setPriority(Thread.MIN_PRIORITY);  
  2. m2.setPriority(Thread.MAX_PRIORITY); 
Daemon Thread
The daemon thread is a service provider thread. It provides services to the user thread. Its life depends on the user threads i.e. when all the user threads dies, JVM terminates this thread automatically.
  • It provides services to user threads for background supporting tasks. It has no role in life than to serve user threads.
  • Its life depends on user threads.
  • It is a low priority thread.
The sole purpose of the daemon thread is that it provides services to user thread for background supporting task. If there is no user thread, why should JVM keep running this thread. That is why JVM terminates the daemon thread if there is no user thread.
The java.lang.Thread class provides two methods related to daemon thread
  • public void setDaemon(boolean status): is used to mark the current thread as daemon thread or user thread.
  • public boolean isDaemon(): is used to check that current is daemon.
  1. class MyThread extends Thread{  
  2.  public void run(){  
  3.   System.out.println("Name: "+Thread.currentThread().getName());  
  4.   System.out.println("Daemon: "+Thread.currentThread().isDaemon());  
  5.  }  
  6.   
  7.  public static void main(String[] args){  
  8.   MyThread t1=new MyThread();  
  9.   MyThread t2=new MyThread();  
  10.   t1.setDaemon(true);  
  11.     
  12.   t1.start();  
  13.   t2.start();  
  14.  }  
  15. }  

Note: If you want to make a user thread as Daemon, it must not be started otherwise it will throw IllegalThreadStateException.

Note: If you have to perform multiple tasks by multiple threads,have multiple run() methods.
Few Questions:
Q1: Valid constructors for Thread? 
Thread(Runnable r, String name) 
Thread() 

Q2: Which method must be defined by class implementing Runnable interface? 
public void run() 

Q3: Which will contain the body of the thread? 
run() method

Q4: What are the three methods of the Object class?
notiy()
notifyAll()
wait(long msecs) 

start() and terminate() methods are defined in class Thread. 
start() method registers a thread in a thread scheduler.

wait() causes current thread to wait until another thread invokes the notify() method or   the notifyAll() method for this object.

Synchronization

One of the biggest pitfalls with multithreaded development is dealing with the fact that threads run in nondeterministic order. 

Each time you execute a multithreaded application, the threads may run in a different order that is impossible to predict. The most challenging result of this nondeterminism is that you may have coded a defect that surfaces only once in a few thousand executions, or once every second full moon.


Two threads that are executing code do not necessarily move through the code at the same rate. One thread may execute five lines of code before another has even processed one. The thread scheduler interleaves slices of code from each executing thread.


All this code interleaving means that you may encounter synchronization issues. If two threads go after the same piece of data at the same time, the results may not be what you expect.


When you send the message join to a thread, execution in the current thread halts until that thread completes.


Synchronized

A thread should be able to execute the entire method, start to finish, without any other thread interfering. You can accomplish this in Java through use of the synchronized method modifier.

public synchronized void withdraw(BigDecimal amount) {
   if (amount.compareTo(balance) > 0)
      return;
   balance = balance.subtract(amount);
}
This implementation of synchronization in Java is known as mutual exclusion. Another way you can refer to the code protected by mutual exclusion is as a critical section. 

In order to ensure that the method code executes mutually exclusively, Java places a lock on the object in which the thread's code is executing. 

While one thread has a lock on an object, no other thread can obtain a lock on that object. Other threads that try to do so will block until the lock is released. The lock is released when the method completes execution.

Java uses a concept known as monitors to protect data. A monitor is associated with each object; this monitor protects the object's instance data. A monitor is associated with each class; it protects the class's static data. When you acquire a lock, you are acquiring the associated monitor; only one thread can acquire a lock at any given time.
You should always try to lock the smallest amount of code possible, otherwise you may experience performance problems while other threads wait to obtain a lock. If you are creating small, composed methods as I've repetitively recommended, you will find that locking at the method level suffices for most needs.
You can lock at a smaller atomicity than an entire method by creating a synchronized block. You must also specify an object to use as a monitor by enclosing its reference in parentheses after the synchronized keyword.
The following implementation of withdraw is equivalent to the above implementation.
public void withdraw(BigDecimal amount) {
   synchronized(this) {
      if (amount.compareTo(balance) > 0)
         return;
      balance = balance.subtract(amount);
   }
}
synchronized block requires the use of braces, even if it contains only one statement.
You can declare a class method as synchronized. When the VM executes a class method, it will obtain a lock on the Class object for which the method is defined.
Synchronized Collections
When you work with the Java 2 Collection Class Framework with classes such as ArrayList, LinkedList, and HashMap, you should be cognizant of the fact that they are not thread-safe—the methods in these classes are not synchronized.
ArrayList, LinkedList and HashMap ----> not thread-safe
Vector and HashTable ----> synchronized
Instead, you can use utility methods in the class java.util.Collections to enclose a collection instance in what is known as a synchronization wrapper. The synchronization wrapper obtains locks where necessary on the targetcollection and delegates all messages off to the collection for normal processing.
Example of adding Synchronization Wrapper:
import java.util.Collections;
List<Search> queue = Collections.synchronizedList(new LinkedList<Search>());
Adding the synchronization wrapper doesn't require you to change any code.

No comments:

Post a Comment