Wednesday, November 25, 2015

Java String, StringBuilder and StringBuffer


What is so different between String, StringBuffer, StringBuilder ?

Strings are simple, constant size and represents a series of characters.
Since they are constants, strings can not be changed and you can simply exchange them.
StringBuilders make them a bit flexible and changeable. While StringBuilder and StringBuffer provides some similar features, StringBuffer is better when it is multi-threaded usage as the methods are synchronized.

A simple example:

public class StringAndStringBuilder {
    public static void changeString(StringBuilder sb){
        sb.delete(0, sb.length());
        sb.append("changed");
    }
public static void changeString(String s){
s="changed";

    }


    public static void main(String[] args) {
        StringBuilder sb=new StringBuilder("nothing");
        changeString(sb);
        System.out.println("value after change via stringbuilder "+ sb);
String s = new String("nothing");
changeString(s);
System.out.println("value after change via string "+ s);

    }
}
output:
value after change via stringbuilder changed
value after change via string nothing

Java Synchronization



Lets see how synchronization works in Java. Below is a sample program which has three parts
- TestSynchronization is a the main class
- TestThread is a private class extends Thread.
- IamSynchronized is one more private class which has synchronized code logic. one part is just a synchronous block and the other is a synchronous method.


public class TestSynchronization {
   public static void main(String args[]) {

      IamSynchronized IS = new IamSynchronized();
      TestThread T1 = new TestThread( "Thread - 1 ", IS );
      TestThread T2 = new TestThread( "Thread - 2 ", IS );
try{Thread.sleep(60000);}catch(Exception e){}
      T1.start();
      T2.start();
   }
}

class TestThread extends Thread {
   private Thread t;
   private String threadName;
   IamSynchronized IS ;
   TestThread(String name, IamSynchronized is){
       threadName = name;
       IS = is;
   }
   public void run() {
     IS.justIterate();
System.out.println("calling sync method - Thread: "+threadName);
IS.syncMethod();
     System.out.println("Thread " +threadName + " done");
   }

   public void start ()
   {
      System.out.println("Starting " +  threadName );
      if (t == null)
      { t = new Thread (this, threadName);
         t.start ();
      }
   }

}

class IamSynchronized {
   public void justIterate(){
    synchronized(this){
try {
         for(int i = 5; i > 0; i--) {
            System.out.println("Iteration --   "  + i );
Thread.sleep(1000);
         }} catch (Exception e) {    System.out.println("Interrupted"+e);  }
}
   }
   public synchronized void syncMethod(){
    {
try {
         for(int i = 5; i > 0; i--) {
            System.out.println("Iteration --   "  + i );
Thread.sleep(1000);
         }
     } catch (Exception e) {
         System.out.println("Interrupted"+e);
     }
   }
}
}

Lets see how the locking works and how the control flow happens when 2 parallel threads trying to execute the same logic.

Starting Thread - 1
Starting Thread - 2
I am in the non synchronous part of justIterate method - Thread Thread - 1
I am Thread Thread - 1  in sync block Iteration --   5
I am in the non synchronous part of justIterate method - Thread Thread - 2        -- THREAD 2 IS BLOCKED BY THREAD1
I am Thread Thread - 1  in sync block Iteration --   4
I am Thread Thread - 1  in sync block Iteration --   3
I am Thread Thread - 1  in sync block Iteration --   2
I am Thread Thread - 1  in sync block Iteration --   1
I am Thread Thread - 2  in sync block Iteration --   5
calling sync method - Thread: Thread - 1  -- THREAD 1 IS BLOCKED BY THREAD2
I am Thread Thread - 2  in sync block Iteration --   4
I am Thread Thread - 2  in sync block Iteration --   3
I am Thread Thread - 2  in sync block Iteration --   2
I am Thread Thread - 2  in sync block Iteration --   1
calling sync method - Thread: Thread - 2  -- THREAD 2 IS AGAIN BLOCKED BY THREAD1 BUT IN SYNC MTHOD
I am Thread Thread - 1  in sync method Iteration --   10
I am Thread Thread - 1  in sync method Iteration --   9
I am Thread Thread - 1  in sync method Iteration --   8
I am Thread Thread - 1  in sync method Iteration --   7
I am Thread Thread - 1  in sync method Iteration --   6
Thread Thread - 1  done
I am Thread Thread - 2  in sync method Iteration --   10  -- SINCE THREAD1 RELEASES LOCK, THREAD2 CONTINUES
I am Thread Thread - 2  in sync method Iteration --   9
I am Thread Thread - 2  in sync method Iteration --   8
I am Thread Thread - 2  in sync method Iteration --   7
I am Thread Thread - 2  in sync method Iteration --   6
Thread Thread - 2  done


Below stack trace gives an idea on how the locks being handled by the JVM


"Thread - 2 " prio=6 tid=0x000000000b550800 nid=0x2478 waiting for monitor entry [0x000000000d48f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at IamSynchronized.justIterate(TestSynchronization.java:47)
        - waiting to lock <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:24)
        at java.lang.Thread.run(Thread.java:722)

"Thread - 1 " prio=6 tid=0x000000000b550000 nid=0x18c4 waiting on condition [0x000000000d17f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at IamSynchronized.justIterate(TestSynchronization.java:49)
        - locked <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:24)
        at java.lang.Thread.run(Thread.java:722)

--------------------------------------------------

"Thread - 2 " prio=6 tid=0x000000000b550800 nid=0x2478 waiting on condition [0x000000000d48f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at IamSynchronized.justIterate(TestSynchronization.java:49)
        - locked <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:24)
        at java.lang.Thread.run(Thread.java:722)

"Thread - 1 " prio=6 tid=0x000000000b550000 nid=0x18c4 waiting for monitor entry [0x000000000d17f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at IamSynchronized.syncMethod(TestSynchronization.java:56)
        - waiting to lock <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:26)
        at java.lang.Thread.run(Thread.java:722)

--------------------------------------------------

"Thread - 2 " prio=6 tid=0x000000000b550800 nid=0x2478 waiting for monitor entry [0x000000000d48f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at IamSynchronized.syncMethod(TestSynchronization.java:56)
        - waiting to lock <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:26)
        at java.lang.Thread.run(Thread.java:722)

"Thread - 1 " prio=6 tid=0x000000000b550000 nid=0x18c4 waiting on condition [0x000000000d17f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at IamSynchronized.syncMethod(TestSynchronization.java:58)
        - locked <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:26)
        at java.lang.Thread.run(Thread.java:722)

--------------------------------------------------

"Thread - 2 " prio=6 tid=0x000000000b550800 nid=0x2478 waiting on condition [0x000000000d48f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at IamSynchronized.syncMethod(TestSynchronization.java:58)
        - locked <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:26)
        at java.lang.Thread.run(Thread.java:722)