Wednesday 27 July 2016

The HelloWorldThread

Multithreading is one of the most powerful features of Java. Also it is the hottest topic in the Java Interviews at some experience level or even for freshers.This is a must know topic for every Java Developer.In every thread related Java interview, the basic understanding of threads will be tested by asking the wait(),notify() and notifyAll() methods. In the following post, you will get a basic idea about them, followed by some basic interview questions related to them.
The Object class in Java has three final methods that allow threads to communicate about the locked status of a resource. These are :

wait() :It tells the calling thread to give up the lock and go to sleep until some other thread enters the same monitor and calls notify() or notifyAll(). It also has a parameterized version wait(long timeout) which can be used to to pass the amount of time the particular thread should wait before it kicks off again even if the notify() is not called.This method must be called from the synchronized block.If the current thread is interrupted while waiting, it will throw the InterruptedException

notify() : It will wake up a single thread on the monitor associated with the synchronized object. If multiple threads are waiting to acquire the lock, only one of them will be notified.However, the awakened thread will still not be able to execute until and unless the lock is released by this thread.

notifyAll() : Almost similar to notify() in many prospects.It will wake up all the threads that are waiting on the monitor associated with the synchronized object.However, if the awakened threads will try to get the lock on the object, only one thread will be given the lock and the rest of them will again go in the waiting state.The awakened threads will complete their execution in the usual manner.

One common characteristic among the three is that they will throw IllegalMonitorStateException if the current thread is not the owner of this object's monitor.

FAQs

Q. What happens to the lock when the wait method is called?
A. It releases the lock on the monitor.
Q. What is the difference between notify() and notifyAll()?
A. notify() wakes up only one of the threads waiting due to the monitor lock whereas notifyAll() wakes up all the threads.
Q. Can we some how control which thread to wake using notify()?
A. No,this can not be controlled.
Q. Why are these methods in Object class and not in Thread class?
A.Because these methods are used for locking which can be performed on objects and not threads. Apart from threads, these methods are the only way to communicate between the two objects.

Implementation of these methods

Write a Program that will start two threads. One thread will be used to print "Hello" and the other thread should print "World". This should be printed 5 times.

This problem can be treated as a classic Producer-Consumer problem. The HelloPrinter can be considered as Producer and the WorldPrinter can be considered as consumer.Both will take turns to do their job in a synchronized environment.

import java.util.concurrent.TimeUnit;

public class HelloWorldThread
{
 private int helloCount=0;
 private int worldCount=0;
 public final int totalCount=5;// 
 
 public static void main(String[] args) {

  HelloWorldThread hwt = new HelloWorldThread();
  //Sharing same object between threads
  Thread ht = new Thread(new HelloPrinter(hwt));
  Thread wt = new Thread(new WorldPrinter(hwt));

  ht.start();
  wt.start();
  
 }

 public int getHelloCount() {
  return helloCount;
 }

 public void setHelloCount(int helloCount) {
  this.helloCount = helloCount;
 }

 public int getWorldCount() {
  return worldCount;
 }

 public void setWorldCount(int worldCount) {
  this.worldCount = worldCount;
 }

}


class HelloPrinter implements Runnable
{

 HelloWorldThread hwt=null;

 public HelloPrinter(HelloWorldThread hwt) 
 {
  this.hwt=hwt;
 }
 @Override
 public void run() {
  try
  {
   synchronized (hwt) //Critical Section begins
   {
    int helloCount=0;
    while(hwt.getHelloCount() < hwt.totalCount)
    {
     if(hwt.getHelloCount()>hwt.getWorldCount())
     {
      hwt.wait();
     }
     helloCount++;
     System.out.print("Hello ");
     TimeUnit.MILLISECONDS.sleep(200);
     hwt.setHelloCount(helloCount);//Updating the count
     hwt.notify();
    }
   }
  }
  catch(InterruptedException e)
  {
   e.printStackTrace();
  }
 }
}

class WorldPrinter implements Runnable
{

 HelloWorldThread hwt=null;

 public WorldPrinter(HelloWorldThread hwt) 
 {
  this.hwt=hwt;
 }
 @Override
 public void run() {
  try
  {
   synchronized (hwt) //Critical Section begins
   {
    int worldCount=0;
    while(hwt.getWorldCount() < hwt.totalCount)
    {
     if(hwt.getHelloCount()==hwt.getWorldCount())
     {
      hwt.wait();
     }
     worldCount++;
     System.out.println("World!!");
     TimeUnit.SECONDS.sleep(1);
     hwt.setWorldCount(worldCount);//Updating the count
     hwt.notify();
    }
   }
  }
  catch(InterruptedException e)
  {
   e.printStackTrace();
  }
 }
}


No comments:

Post a Comment