Recent Posts

Sunday, 7 August 2016

Threads And Concurrency Tutorial Part 3


Interrupting a thread
       We can interrupt a sleeping or waiting thread by using interrupt method of thread class.
public void interrupt()
E.g
class MyThread extends Thread {
   public void run() {
      try {
         for (int i = 0; i < 5; i++) {
            System.out.println("Child Thread :" + i);
            Thread.sleep(2000);
         }
      } catch (InterruptedException e) {
         System.out.println("I got interrupted");
      }
   }
}

public class MyThreadInterrupt {
   public static void main(String[] args) {
      MyThread t = new MyThread();
      t.start();
      t.interrupt(); 
      System.out.println("Main thread");
   }
}
Output
Main thread
Child Thread :0
I got interrupted
Note
* Whenever we are calling interrupt() method we may not see the effect immediately, if the target Thread is in sleeping or waiting state it will be interrupted immediately.

* If the target Thread is not in sleeping or waiting state then interrupt call will wait until target Thread will enter into sleeping or waiting state. Once target Thread entered into sleeping or waiting state it will effect immediately.

* In its lifetime if the target Thread never entered into sleeping or waiting state then there is no impact of interrupt call simply interrupt call will be wasted.
E.g
class MyThread extends Thread {
   public void run() {
      for (int i = 0; i < 5; i++) {
         System.out.println("Child Thread :" + i);
      }
      try {
         Thread.sleep(2000);
      } catch (InterruptedException e) {
         System.out.println("Thread got interrupted");
      }
   }
}

public class MyThreadInterrupt {
   public static void main(String[] args) {
      MyThread t = new MyThread();
      t.start();
      t.interrupt(); 
      System.out.println("Main thread");
   }
}
Output
Main thread
Child Thread :0
Child Thread :1
Child Thread :2
Child Thread :3
Child Thread :4
Thread got interrupted
* In the above program interrupt() method call invoked by main Thread will wait until child Thread entered into sleeping state.

* Once child Thread entered into sleeping state then it will be interrupted immediately.



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.
E.g
class Display {
   public synchronized void wish(String name) {
      for (int i = 0; i < 5; i++) {
         System.out.print("Hello ");
         try {
            Thread.sleep(1000);
         } 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);
   }
}

public class MySynchronized {
   public static void main(String[] args) {
      Display d = new Display();
      MyThread t1 = new MyThread(d, "Ashok");
      MyThread t2 = new MyThread(d, "Vinod");
      t1.start();
      t2.start();
   }
}
Output
Hello Ashok
Hello Ashok
Hello Ashok
Hello Ashok
Hello Ashok
Hello Vinod
Hello Vinod
Hello Vinod
Hello Vinod
Hello Vinod
     If we are not declaring wish() method as synchronized then both Threads will be executed simultaneously and we will get irregular output.
Hello Hello Ashok
Hello Vinod
Hello Ashok
Hello Vinod
Hello Ashok
Vinod
Hello Hello Ashok
Hello Vinod
Hello Vinod
Ashok
Case 1
Display d1 = new Display();
Display d2 = new Display();
MyThread t1 = new MyThread(d1, "Ashok");
MyThread t2 = new MyThread(d2, "Vinod");
t1.start();
t2.start();
     Even though we declared wish() method as synchronized but we will get irregular output in this case, because both Threads are operating on different objects.
Hello Hello Vinod
Hello Ashok
Hello Ashok
Hello Vinod
Hello Ashok
Hello Vinod
Hello Ashok
Hello Vinod
Hello Ashok
Vinod
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).

Class level lock
* Every class in java has a unique lock. If a Thread wants to execute a static synchronized method then it required class level lock.

* Once a Thread got class level lock then it is allow to execute any static synchronized method of that class.

* While a Thread executing any static synchronized method the remaining Threads are not allow to execute any static synchronized method of that class simultaneously.

* But remaining Threads are allowed to execute normal synchronized methods, normal static methods, and normal instance methods simultaneously.

* Class level lock and object lock both are different and there is no relationship between these two.

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.

* The main advantage of synchronized block over synchronized method is it reduces waiting time of Thread and improves performance of the system.
E.g
     To get lock of current object we can declare synchronized block as follows. If Thread got lock of current object then only it is allowed to execute this block.
Synchronized(this){

}
   To get the lock of a particular object 'b' we have to declare a synchronized block as follows. If thread got lock of 'b' object then only it is allowed to execute this block.
Synchronized(b){

}
     To get class level lock we have to declare synchronized block as follows.
Synchronized(Display.class){

}
     If thread got class level lock of Display then only it allowed to execute this block.

Note
     As the argument to the synchronized block we can pass either object reference or ".class file" and we can't pass primitive values as argument [because lock concept is dependent only for objects and classes but not for primitives].

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.

* If a thread wants to call wait(), notify() and notifyAll() methods compulsory the Thread should be owner of the object. i.e., the Thread has to get lock of that object. i.e., the Thread should be in the synchronized area.

* Hence, 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.

* Thread releases the lock of only current object but not all locks. After calling notify() and notifyAll() methods Thread releases the lock but not immediately. Except these wait(), notify(), notifyAll() there is no other case where Thread releases the lock.


1. public final void wait()throws InterruptedException
2. public final native void wait(long ms)throws InterruptedException
3. public final void wait(long ms,int ns)throws InterruptedException
4. public final native void notify()
5. public final void notifyAll()
E.g
package com.ashok.threads;

public class Test {
   public static void main(String arg[]) throws InterruptedException {
      MyThread thread = new MyThread();
      thread.start();
      System.out.println("Inside Main Method");
      Thread.sleep(100);
      System.out.println(thread.total);
   }
}

class MyThread extends Thread {
   int total = 0;
   public void run() {
      System.out.println("Child Starting calculation");
      for (int i = 1; i <= 50; i++) {
      if (i == 1)
         System.out.println("Inside for loop ");
      total = total + i;
      }
   }
}
Output
Inside Main Method
Child Starting calculation
Inside for loop 
1275
     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.
package com.ashok.threads;

public class Test {
   public static void main(String arg[]) throws InterruptedException {
      MyThread thread = new MyThread();
      thread.start();
      synchronized (thread) {
         System.out.println("Main Method calling wait method ");
         thread.wait();
         System.out.println("Main Got Notification");
         System.out.println(thread.total);
      }
   }
}

class MyThread 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();
      }
   }
}
Output
Main Method calling wait method 
Child Starting calculation
Child Giving notification
Main Got Notification
1275
notify() vs notifyAll()
* 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.
E.g
Producer consumer problem
* Producer(producer Thread) will produce the items to the queue and consumer(consumer thread) will consume the items from the queue. If the queue is empty then consumer has to call wait() method on the queue object then it will entered into waiting state.

* After producing the items producer Thread call notify() method on the queue to give notification so that consumer Thread will get that notification and consume items.

No comments:

Post a Comment