Custom BlockingQueue implementation in java

Producer Consumer using custom BlockingQueue implementation in java


Implement a custom Blocking Queue is very popular interview question.

What is Blocking Queue?

BlockingQueue is a queue data structure that blocks all the threads trying to read(Consumer) the data from the queue if the queue is empty and similarly it blocks all the threads trying to add(Producer) the data to the queue if the queue is full. due to this blocking feature, the queue is known as BlockingQueue. 

Threads that are blocked for adding the data to the queue due to queue full gets unblocked when some other thread removes the data from the queue and there is a space to add new data.

Threads that are blocked for reading the data from the queue due to queue empty gets unblocked when some other thread adds the data to the queue and there is some data to read.

Note: BlockingQueue doesn't accept null values, If we try to add null, then it throws NullPointerException.
Custom BlockingQueue implementation in java
Custom BlockingQueue implementation in java

I would recommend going through below articles for better understanding of Threads and synchronization in Java.


Implement Custom BlockingQueue in Java


 
package javabypatel;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class CustomBlockingQueueUsingLock {
    private Lock lock = new ReentrantLock();
    private Condition putCondition = lock.newCondition();
    private Condition takeCondition = lock.newCondition();

    private Object[] queue;
    private int queueSize;

    private int putIndex;
    private int takeIndex;
    private int count;

    public CustomBlockingQueueUsingLock(int queueSize) {
        this.queueSize = queueSize;
        queue = new Object[queueSize];
    }

    public void put(Object data) {
        lock.lock();
        try{
            while (count >= queueSize) {
                try {
                    putCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("Queuing value :" + data);
            queue[putIndex] = data;
            count++;

            if (++putIndex >= queueSize) {
                putIndex = 0;
            }
            takeCondition.signalAll();
        }  finally {
            lock.unlock();
        }
    }

    public Object take() {
        lock.lock();
        try {
            while (count == 0) {
                try {
                    takeCondition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Object data = queue[takeIndex];
            count--;

            if (++takeIndex >= queueSize) {
                takeIndex = 0;
            }
            putCondition.signalAll();
            return data;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        CustomBlockingQueueUsingLock customBlockingQueue = new CustomBlockingQueueUsingLock(5);

        new Thread(() -> {
            int i = 0;
            while (i < 10) {
                System.out.println("data :" + customBlockingQueue.take());
                i++;
            }
        }, "Consumer Thread").start();

        new Thread(() -> {
            int i = 0;
            while (i < 10) {
                customBlockingQueue.put(i);
                i++;
            }
        }, "Producer Thread").start();
    }
}
 

Implement Custom Generic blocking queue using Linked list data structure and Locks in Java


package javabypatel;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class GenericCustomBlockingQueueUsingLock<T> {
    private Queue<T> queue = new LinkedList<T>();

    private Lock lock = new ReentrantLock();
    private Condition putCondition = lock.newCondition();
    private Condition takeCondition = lock.newCondition();

    private int size;

    public GenericCustomBlockingQueueUsingLock(int size) {
        this.size = size;
    }

    public T take() throws InterruptedException {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                takeCondition.await();
            }
            T data = queue.poll();

            //If say the queue is full before we take, then chances are threads trying to put would be waiting, so after taking the
            //element we will inform put threads that there is space now for you to put.
            putCondition.signal();
            return data;
        } finally {
            lock.unlock();
        }
    }

    public void put(T obj) throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == size) {
                putCondition.await();
            }
            System.out.println("Putting data :" + obj);
            queue.add(obj);

            //If say the queue is empty before we add the element to the queue, then chances are threads trying to take the element would be waiting,
            //so after adding the element we will inform take threads that there is element now for you to take.
            takeCondition.signal();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        GenericCustomBlockingQueueUsingLock<Integer> queue = new GenericCustomBlockingQueueUsingLock<>(10);
        new Thread(() -> {
            int i = 0;
            while (i < 20) {
                try {
                    System.out.println(queue.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i++;
            }
        }).start();

        new Thread(() -> {
            int i = 0;
            while (i < 20) {
                try {
                    queue.put(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i++;
            }
        }).start();
    }
}

When to use volatile vs synchronized in Java

When to use volatile vs synchronized in Java


When to use volatile and synchronized keyword in Java is very important to understand as without the understanding you may go wrong in communicating between threads.




synchronized keyword:

synchronized keyword is used at method level and block level, but the whole purpose of synchronized keyword is to apply access restrictions as only one thread holding the monitor would be able to execute the code inside synchronized method/block.

volatile keyword:

Volatile keyword is used when you don't want local CPU core to cache the variable from main memory, instead all read/write to volatile variable should happen directly from main memory.

The Java volatile keyword guarantees visibility of changes to variables across threads.

So lets understand with practical scenario when to use which,

Scenario 1:
If multiple threads are trying to read the value of a variable and based on the current value it takes the decision of incrementing or decrementing a variable value, is marking a variable volatile in this situation enough?

No, Volatile only guarantees visibility, check and act is like we want two operations to be atomic in that case we either need to use synchronized method/block or Atomic variables (AtomicInteger for example).

Scenario 2:
There are multiple threads reading the value of shared variable but only one thread is writing to a shared variable, is marking a variable volatile in this situation enough?

Yes. as is there no situation where we need more than one operation to be atomic here and also only one thread is writing to a variable others are simply reading the shared variable, so volatile variable should work.

So to summarize, there are 3 problems associated with Multithreading,
  1. Race Conditions. (check and act, like i++, i--)
  2. Local CPU Caching OR Stale memory. (Threads running in CPU, caches the value from main memory to local CPU cache and now main memory and local CPU cache is out of sync)
  3. Complier and CPU optimization (VM/CPU are free from reordering the instructions in the program for optimization and performance as long as the meaning of the instructions remain same.)

Volatile helps in resolving the problem happens due to point 2 and 3 but not 1.

Synchronization helps in resolving all of the above points.

Example demonstrating need of volatile keyword in Java

package javabypatel;

public class VolatileExample extends Thread {

    //Remove the volatile keyword and see
    volatile boolean keepRunningFlag = true;

    public void run() {
        System.out.println("Volatile thread running");
        long counter = 0;
        while (keepRunningFlag) {
            counter++;
        }
        System.out.println("Volatile thread terminated." + counter);
    }

    public static void main(String[] args) throws InterruptedException {
        //Code below is executing under Main Thread
        VolatileExample volatileThread = new VolatileExample();
        volatileThread.start();

        Thread.sleep(1000);

        //Main Thread is changing the value of keepRunningFlag to false. Ideally after this changes,
        //volatileThread created above executing the run method should come out of the while loop,
        //but if you don't declare the variable keepRunningFlag as volatile then there is no guarantee when while loop will break.
        //How this works internally without volatile keyword,
        //Main thread say running in CPU core 1 updates the keepRunningFlag to false which is updated in Main thread CPU cache
        //volatileThread say running in CPU core 2 also has local CPU cache which before starting the thread had cached the variable
        //keepRunningFlag to its local cache as false.
        //So any updates on the local variable not marked as volatile will first get updated to its local CPU cache.
        //No when the local cache value will sync with Main memory is internal to CPU and that is where problem happens.
        //When we mark the variable as volatile, we are instructing CPU as not to read/write the value of this variable to
        //your local cache, instead directly read/write from main memory.
        volatileThread.keepRunningFlag = false;

        System.out.println("Main thread ended, keepRunningFlag = " + volatileThread.keepRunningFlag);
    }
}



Check the program below, what do you think we should use volatile or synchronization in below situation

package javabypatel;

public class DBConnection {
    private boolean connected;

    public synchronized void setConnectionFlag(boolean connected) {
        this.connected = connected;
    }
    public synchronized boolean isConnected() {
        return connected;
    }
}
Think of synchronized keyword when you want to make more than one instruction to be marked as single unit that is Atomic operation.

Example: i++ where the operation is break down as,
1. Reading the value of i first
2. Incrementing the value of i.

So that is two step operation and you want to make this two step as a single Atomic operation.

Think of volatile when you want to resolve the issues of visibility, like updates from one thread should be immediately available to other thread for taking some action but there is no operation that you want to execute as atomic, like the example above. In the above example we are simply setting the value of connected in setConnectionFlag method and we are simply returning the value of connected variable in isConnected method, so better to mark the connected variable as volatile in this situation instead of marking the method as synchronized.

Remember whatever you could do with volatile keyword can also be done using synchronized but with synchronized keyword you also get the feature of making the multi step instructions as Atomic operation.

Using synchronized and volatile keyword together.

There may be a situation where you may need to use volatile and synchronized keyword together. In the example below we are using for the reason of performance.

package javabypatel;

public class SingletonTest {
    volatile static SingletonTest instance = null;

    public static SingletonTest getInstance() {
        if (instance == null) {
            synchronized (SingletonTest.class) {
                if (instance == null) {
                    instance = new SingletonTest();
                    System.out.println("instance created");
                }
            }
        }
        return instance;
    }
}

In the example above since the outer line "if (instance == null)" is not inside synchronized block, what will happen is, say if Thread A gets a chance and is executing the line "instance = new SingletonTest();" and after that it gets preempted. Now, what will Thread 2 see which reached the line "if (instance == null) {" outside the synchronized block, whether the instance would be null or non-null. possibly it may see null if the local cache of the thread 1 is not flushed. so to make sure Thread 2 see the update value of the instance variable instance is marked as volatile here.

You may also like to see


How ConcurrentHashMap works and ConcurrentHashMap interview questions.

How Thread.join() in Java works internally

Exception Handling Interview Question-Answer

Method Overloading - Method Hiding Interview Question-Answer

Type Casting Interview Questions In Java

How is ambiguous overloaded method call resolved in java

Method Overriding rules in Java

Interface interview questions and answers in Java

Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.

Generate all the binary strings of N bits.

Generate all the binary strings of N bits. 


Given a positive integer number N. Generate all the binary strings(0 and 1) of N bits. 

Case 1
 Input: length=2
 Output:
 0 0
 0 1
 1 0
 1 1

Case 2
 Input: length=3
 Output:
 0 0 0
 0 0 1 
 0 1 0
 0 1 1
 1 0 0
 1 0 1
 1 1 0
 1 1 1

Case 3
 Input: length=1
 Output:
 0
 1

Algorithm:


We will see two approach of generating the binary string combination. 

First approach, where we will form the binary string one by one and once it matches the required length, we will backtrack and switch the binary digit. In this approach, as String is immutable each character we append to a String will create new String object.

Recursive stack trace of Generating all the binary strings of N bits.
generate all binary strings of length n with k bits set
Generate all the binary strings of N bits.

Second approach, In the first approach, each time we append the new character to String, a new String literal is created, so why to waste the space. In this approach we will use the fixed size array so that anytime we iterate and use the array we will always be working on fixed size array.

for more details on String and Memory management in Java, visit Java Memory Management Interview Questions

Java Program to Generate all the binary strings of N bits.


package javabypatel;
 
public class GenerateBinaryString {
 
    public void printBinaryCombination(int length, String str) {
        if (str.length() == length) {
            System.out.println(str);
            return;
        }
        printBinaryCombination(length, str + "0");
        printBinaryCombination(length, str + "1");
    }
 
    public static void main(String[] args) {
        GenerateBinaryString obj = new GenerateBinaryString();
        int length = 3;

        System.out.println("Approach 1");
        obj.printBinaryCombination(length, "");
    }
}

Optimized Approach: Using Array so no new String is created when a character is appended each time


package javabypatel;
 
import java.util.Arrays;
 
public class GenerateBinaryString {
 
    public void printBinaryCombination(int index, int[] arr) {
        if (index == arr.length) {
            System.out.println(Arrays.toString(arr));
            return;
        }
        arr[index] = 0;
        printBinaryCombination(index + 1, arr);
        arr[index] = 1;
        printBinaryCombination(index + 1, arr);
    }
 
    public static void main(String[] args) {
        GenerateBinaryString obj = new GenerateBinaryString();
        int length = 3;
 
        System.out.println("Approach 2");
        obj.printBinaryCombination(0, new int[length]);
    }
}

You may also like to see


Write a program to print all permutations of a given string without repetition. (Repetition of characters is not allowed).

Write a program to print all permutations of a given string with repetition. (Repetition of characters is allowed).

Print all subsets of a given set.

Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.

Check if an array is sorted in Java - Iterative and Recursive approach

Check if an array is sorted in Java - Iterative and Recursive approach.


Given an array, check if it is already sorted or not using both Iterative and Recursive way.

Lets see sample input and output for better understanding:
Check whether the array is sorted in Java
Check whether array is sorted or not

Simple Deadlock Program in Java

Simple java program to create Deadlock.


Deadlock describes a situation where two or more threads are blocked forever, waiting for each other.


Let's consider an example, in the office we have shared Printer and Scanner where Employees has ability to do scanning and printing.

1. John has bunch of documents that it wants to Print first and also want to take a Scan later.
(Print and Scan)

2. Michael has bunch of documents that it wants to Scan first and also want to take a Print later.
(Scan and Print)

Difference between process and thread

Difference between process and thread.


Point 1:
A process is an executing instance of an application.
Thread is independent path of execution within a process. Process can have multiple threads,

Point 2:
Threads itself is capable enough to do all the things a process does and thread is a part of process that is why thread can be termed as light-weight process.

Point 3:
Since all the Threads are part of a same Process they all share same memory allocated by Process.
Process use memory allocated by OS.

Point 4:
Inter-thread communication between threads is easy whereas Inter-process communication is difficult.

Point 5:
Processes have independent data and code segments.
Thread shares the data segment, code segment, files etc. with its peer threads.

Point 6:
Process switching is complex as compared to thread switching because of the amount of variables need to be maintained in both of the case.

Per process items Per thread items
Address space  Program counter
Global variables Registers
Open files Stack
Child processes State
Pending alarms
Signals and signal handlers
Accounting information

Difference between CountDownLatch and CyclicBarrier in Java

Difference between CountDownLatch and CyclicBarrier in Java?


Difference 1:

In CountDownLatch, main thread which mostly invokes latch.await() waits for other threads to call countDown() and count reaches 0. In CyclicBarrier, threads wait for each other to complete their execution and reach at common point after which barrier is opened.


Note in CountDownLatch, it is not necessary same thread calls latch.countDown() 10 times or 10 threads calling latch.countDown and making the counter 0 but in case of CyclicBarrier different threads should reach at the common barrier point.

Let's see example of CyclicBarrier

package com.javabypatel.practice;

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
    
    public static void main(String args[]) {
        final CyclicBarrier cb = new CyclicBarrier(3, new Runnable(){
            @Override
            public void run(){
                System.out.println("Start the Game");
            }
        });

        Thread player1 = new Thread(new Player(cb), "Thread1");
        Thread player2 = new Thread(new Player(cb), "Thread2");
        Thread player3 = new Thread(new Player(cb), "Thread3");

        player1.start();
        player2.start();
        player3.start();
    }
}

class Player implements Runnable {

    private CyclicBarrier barrier;
    public Player(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + " is waiting on barrier");
            barrier.await();
            System.out.println(Thread.currentThread().getName() + " has passed the barrier");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Output:
Thread1 is waiting on barrier
Thread2 is waiting on barrier
Thread3 is waiting on barrier
Start the Game
Thread3 has passed the barrier
Thread2 has passed the barrier
Thread1 has passed the barrier

Difference 2:

CountDownLatch can not be reused once count reaches 0. CyclicBarrier can be reinitialized once parties reaches 0.

Difference 3:

CountDownLatch calls countDown() method to reduce the counter where as CyclicBarrier calls await() method to reduce the counter. Note, await() method blocks the thread from further execution until all thread reaches to a common barrier, countDown() method doesn't block anything.

Difference 4:

CountDownLatch can not trigger common event when count reaches 0, that is when count reaches 0, it just unblocks the blocked thread and proceed with executing further instructions.

CyclicBarrier can trigger common event (Runnable) once it reaches to a barrier point.
Example: refer above

Difference 5:

CyclicBarrier is used for map-reduce kind of operations, like say we want to count population on India, so we will create say 4 threads which counts the population of East, West, North and South.

Each thread will count the population of its Region, we also need to merge the result when data from all threads is ready until which merging cannot be done.

We can create a CyclicBarrier and block the thread after it finds the count, so all threads are blocked after counting the population of its respective region, once all thread reaches barrier, it is broken and merger(Runnable event) can be executed to count the population.

CountDownLatch is used when we want all thread to reach at common event but doesn't necessarily want to block them at that point and they can proceed after signaling(latch.countDown()), Say for example, if we want to start the client file poller after database service(thread1) and ConnectionPoolService with 100 threads(thread2) is up, so we can wait for thread1 and thread2 to call countDown() after which blocked main thread can proceed with starting client file pooler.


You may also like to see


Advanced Java Multithreading Interview Questions & Answers

Type Casting Interview Questions and Answers In Java?

Exception Handling Interview Question-Answer

Method Overloading - Method Hiding Interview Question-Answer

How is ambiguous overloaded method call resolved in java?

Method Overriding rules in Java

Interface interview questions and answers in Java


Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.

Difference between Join and CountDownLatch in Java

Difference between Join and CountDownLatch?



Difference 1:

Thread join method waits for other thread to finish before further executing current thread.
If t1.join is called in main thread, then main thread will wait at that point until t1 finishes its job.

CountDownLatch on the other end wait for its counter to reach 0 before executing current thread.
ExecutorService service = Executors.newFixedThreadPool(5);
final CountDownLatch latch = new CountDownLatch(3);

for(int i = 0; i < 5; i++) {
    service.submit(new Runnable() {
        public void run() {
            latch.countDown();
        }
    });
}

latch.await();

When latch.countDown is called, associated counter will be decremented and as soon as it reaches 0, main thread which was blocked at line latch.await() proceeds further.


Note:
Thread join method wait for joined thread to finish the execution before the main thread on which join method is called to starts its execution. Whereas in CountDownLatch, latch.await doesn't wait for the thread that calls latch.countDown() to be finished, it proceeds once the counter value reaches 0 and it has no association with the state of the thread that calls countDown().

Difference 2:

We can call join method when we have control over the threads but while using ExecutorService we don't have control over individual threads instead we deal with just submitting the task to framework and it internally manages threads in this situation using CountDownLatch is right approach.

Example above in difference 1 can be used as Reference.


Usage:

Example 1:
CountDownLatch is useful in Multiplayer games, Lets say we have a online chess game that can only be played when two player joins, in this case we will initialize the CountDownLatch to 2 and starts the game only after 2 threads(player) joins(calls countDown()).

Example 2:
Lets say we have some Timer task that we want to start only after all the modules of the application get loaded or when all the services is up.
 

You may also like to see


Advanced Java Multithreading Interview Questions & Answers

Type Casting Interview Questions and Answers In Java?

Exception Handling Interview Question-Answer

Method Overloading - Method Hiding Interview Question-Answer

How is ambiguous overloaded method call resolved in java?

Method Overriding rules in Java

Interface interview questions and answers in Java


Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.

ReentrantLock interview questions in Java

ReentrantLock interview questions in Java


Reentrant lock is more feature rich than using synchronized method/block.

This post assume you have basic idea about Threads and synchronization in Java, If not I recommend going through below Multithreading articles first,
When using synchronized method or a synchronized block, process of lock acquisition and release is actually handled internally but with Reentrant Lock, programmer has full control over thread locks and thread locking management is on developer by explicitly calling lock and unlock method, so there is both advantages and disadvantages of this Reentrantlock.
reentrantlock interview questions in java
Reentrantlock interview questions in java

Question 1: What is the difference between ReentrantLock and Synchronized keyword in Java?


Time to wait for getting a Lock:

When a thread invoke synchronized method or a block, It has to first acquire a lock and then only it can proceed, there is no control to programmer over a time a thread should keep waiting for lock. 

Lets understand above point with an example, When thread 1 tries to call any synchronized method or synchronized block, It has to wait until some other thread say thread 2 release the lock on the same monitor. What if the thread 2 doesn't release the monitor due to some reason, How much time thread 1 has to wait, there is no control to the programmer till when Thread 1 will be waiting.

Using ReentrantLock which was introduced in jdk 1.5 under java.util.concurrent.locks package, We can provide a timeout till when thread should keep waiting for acquiring a lock and after that time thread will proceed with normal execution. this will give more control to threads while waiting for a lock instead of indefinitely waiting or getting blocked till lock is acquired.

Example: tryLock method,
  
Lock lock = new ReentrantLock();
lock.tryLock(long timeout, TimeUnit unit)
Complete trylock example in Java
package javabypatel;

import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadSafeArrayList<E> {
    public static void main(String[] args) throws Exception {
        final ReentrantLock lock1 = new ReentrantLock();
        final ReentrantLock lock2 = new ReentrantLock();

        String printerLock = "PrinterLock";
        String scannerLock = "ScannerLock";

        Runnable try1_2 = getRunnable(lock1, printerLock, lock2, scannerLock);
        Runnable try2_1 = getRunnable(lock2, scannerLock, lock1, printerLock);
        Thread t1 = new Thread(try1_2);
        t1.start();
        Thread t2 = new Thread(try2_1);
        t2.start();
    }

    private static Runnable getRunnable(final ReentrantLock lock1, final String lock1Name,
        final ReentrantLock lock2, final String lock2Name) {
        return new Runnable() {
            @Override
            public void run() {
                try {
                    if (lock1.tryLock(5, TimeUnit.SECONDS)) {
                        System.out.println(lock1Name + " acquired by thread " + Thread.currentThread());

                        Random rand = new Random();

                        if (lock2.tryLock(rand.nextInt(10), TimeUnit.SECONDS)) {
                            System.out.println(lock2Name + " acquired by thread " + Thread.currentThread());
                            Thread.sleep(2000);
                        } else {
                            System.out.println("Could not acquire " + lock2Name + " by thread " + Thread.currentThread());
                            lock1.unlock();
                            System.out.println(lock1Name + " released by thread " + Thread.currentThread());
                        }
                    } else {
                        System.out.println("Unable to acquire " + lock1Name + " by thread " + Thread.currentThread());
                    }
                } catch (InterruptedException e) {
                    System.out.println("I am interrupted" + Thread.currentThread());
                } finally {
                    if (lock1.isHeldByCurrentThread())
                        lock1.unlock();
                    if (lock2.isHeldByCurrentThread())
                        lock2.unlock();
                }
            }
        };
    }
}
Fairness policy:

When thread (say thread 1) calls synchronized method or synchronized block, it has to first acquire the monitor and then only can enter inside synchronized area. If monitor is acquired by other thread say thread 2 then thread 1 has to wait. 

Also, there can be many threads(say thread 1, thread 5, thread 8 etc) waiting for the same monitor. what will happen when thread 2 release the lock on monitor, which thread will be the next to execute among thread 1, thread 5, thread 8 waiting for lock? 

There is no guarantee which thread will get the control and that totally depends on scheduler, this leads to problem of thread (say thread 1) not getting monitor even though it is waiting for longest time among other threads for acquiring the lock and other thread (say thread 5) gets the monitor even if it just joined the waiting queue. ReentrantLock solves this problem by adding fairness policy while creating 
ReentrantLock  object.

While creating a ReentrantLock object, we can provide fairness property for making the lock fair. Fairness property provides lock to longest waiting thread, in case of contention. With fairness enabled, Threads get the lock in the order they requested it.

Example:
  
  ReentrantLock lock = new ReentrantLock(true);

Note: Performance is degraded by fairness policy.

LockInterruptibly

When thread 1 calls the synchronized method or synchronized block, it will be blocked until lock on the monitor is available. programmer don't have control to resume the blocked thread.
ReentrantLock provides a method called lockInterruptibly(), which can be used to interrupt the thread when it is waiting for lock. so that it can no longer in blocked state indefinitely.

void lockInterruptibly()
If thread is able to acquire lock then this method increments lock hold count by 1.
If the lock is with another thread then the current thread waits until it gets the lock or some other thread interrupts the thread.

lockinterruptibly example in java:
public class LockInterruptiblyExample{
 final ReentrantLock reentrantLock = new ReentrantLock();
 
 public void performTask() {
      try {
       reentrantLock.lockInterruptibly(); //wait till thread get the lock or till other thread interrupts
         //and you can control further execution from catch block
       try {
         //.....
       } finally {
      reentrantLock.unlock();
       }
      } catch (InterruptedException e) {
       e.printStackTrace();
      }
 }
} 


Number of Threads blocked on monitor:

Using synchronized method or block doesn't provide any mechanism to know how many threads are blocked to acquire a lock on monitor
Reentrant lock provides getQueueLength() method which return number of threads that may be waiting to acquire this lock in java.


Lock Unlock in different scope

With Synchronized keyword, lock need to be acquired and released at complete method level or at block level. Lets say when thread t1 tries to acquire multiple locks by calling multiple synchronized method, in that case multiple locks are acquired by t1 and they must all be released in the opposite order.

In ReentrantLock, locks can be acquired and released in different scopes, and allowing multiple locks to be acquired and released in any order.

Example:

ReentrantLock reentrantLock;

public void getA() {
  reentrantLock.lock();
}

public void getB() {
  reentrantLock.unlock();
}


More than one waiting condition

When lock is acquired using intrinsic lock by calling synchronized method/block, this threads then communicate using wait(), notify() and notifyAll() methods of Object class.

Condition allows inter thread communication when lock is acquired using extrinsic way by Lock interface. Condition defines methods such as await(), signal() and signalAll() for waiting and notifying.

Using synchronized block/method for a common monitor, there is no way to distinguish for what reason each thread is waiting, thread t1, t2, t3 might be blocked say for putting the data in the queue, other threads say t5, t6, t7, t8 might be waiting for reading data from the queue and they all are waiting on common monitor "queue".

Lets consider producer consumer situation, say we have a queue of size one and is full and t1, t2, t3 is blocked for putting the data in the queue, so they are in waiting state.
Now, t5, t6, t7, t8 tries to read data from the queue, lets say t5 would be reading the data in the queue, meanwhile t6, t7, t8 would be in waiting state.

After t5 read the data from the queue, it calls notifyAll, this call is to notify producers(t1,t2,t3) to put the data in the queue as there is a space now,
there are total 6 threads waiting for monitor "queue"
putting data in queue = t1, t2, t3,
reading data from queue = t4, t6, t7
currently monitor is held by executing thread = t5

when t5 calls notifyAll, there is no guarantee who is going to be wake up, might be thread t7 wake up and it has to go back to waiting state again as nothing is there to read, next time might be t4 gets a chance and again no use of t4 wakeup and it will go back to waiting state.
When someone from t1, t2 or t3 wakes up then only things would proceed.

If there is a way for t5 thread to notifyAll only to threads that want to put data to queue t1, t2 and t3 then it would be helpful. Using Condition that is possible.

With intrinsic lock using synchronized method/block there is no way to group the waiting threads waiting on a common monitor. with Condition, we can create multiple wait sets.

When you use Condition: await()/signal() you can distinguish which object or group of objects/threads get a specific signal.

Using Condition, we now have way to create more than one condition variable per monitor.
Monitors that use the synchronized keyword can only have one. This means Reentrant locks(implementation of Lock interface) support more than one wait()/notify() queue.

    private final Lock lock = new ReentrantLock();
    private final Condition queueEmpty = lock.newCondition();
    private final Condition queueFull = lock.newCondition();

    public void putData(int data) {
        lock.lock();
        try {
            while (queue is empty) {
                queueEmpty.await();
            }
            this.data = data;
            queueFull.signalAll();
                      
        } finally {
            lock.unlock();
        }
    }

    public void getData() {
        lock.lock();
        try {
            while (queue is full) {
                queueFull.await();
            }
            queueEmpty.signalAll();
        } finally {
            lock.unlock();
        }
    }


Now with queueFull.signalAll(), only threads those are waiting for this condition on same monitor "lock" will be awaked and rest will still be waiting.

Condition interface also comes with useful method that is:
boolean awaitUntil(Date deadline): Causes the current thread to wait until it is signaled or interrupted, or the specified deadline elapses.

Note: there is similar method wait(long timeInMilliseconds), but when there is System date change, above method will have impact while wait will keep waiting for provided timeInMilliseconds. So decide which is better in your situation.

Question 2. Does synchronized method and block are reentrant?

Yes. synchronized method, synchronized block and Reentrant lock are all reentrant in nature.

What is the meaning of Reentrant?
A reentrant lock is one where a process can claim the lock multiple times without blocking on itself.
In simple terms, ability to call the same synchronized method again and again without getting blocked is called reentrant.

Lets understand with example,
synchronized  void getA () {
    getB();
}

synchronized void getB () {
    getA();
}

What will happen if say Thread 1 calls obj.getA(), thread 1 will  acquire a lock on obj and call method getA(). inside which it calls getB()(which is obj.getB()), thread 1 already hold the lock on obj so it will call getB(), 
getB() call getA()(which is obj.getA()), thread 1 already hold a lock on obj so it is allowed to call the method getA() again. this is called Reentrant. same lock is claimed multiple times that is each time getA is called.


Question 3. Show simple example on how to write lock and unlock method of Reentrant Lock? 
public void getA() { 
      reentrantLock.lock(); 
      try{ 
          //...
      } catch(Exception e) { 
          e.printStackTrace(); 
      } finally { 
          reentrantLock.unlock(); 
      }     
} 




Question 4. Why ReentrantLock is called ReentrantLock?

ReentrantLock keep track of lock acquisition count associated with the lock.
when a call reentrantLock.lock() is made to acquire a lock and if the lock is obtained then the acquisition count variable is incremented to 1, stating that lock has been acquired one time till now.

Similarly, when a call reentrantLock.unlock() is made acquisition count variable is decremented by 1.
When the count reaches 0 then only other thread will be allowed to take the lock.

When a thread t1 acquires a reentrant lock inside method say getA() and make a call to another method say getB() from inside getA() which is also guarded by reentrant lock, in this case thread t1 will acquire a lock twice one for getA() method and one for getB() method. In this case, if a thread t1 that is already holding a lock is now acquiring it again inside getB(), the acquisition count is incremented to 2 and now the lock needs to be released twice to fully release the lock.

Let's see sample program,

package com.javabypatel.concurrency;

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();

        Thread t1 = new Thread(new Printer("Thread1", reentrantLock));
        Thread t2 = new Thread(new Printer("Thread2", reentrantLock));

        t1.start();
        t2.start();
    }
}

class Printer implements Runnable {

    private String threadName;
    private ReentrantLock reentrantLock;

    Printer(String threadName, ReentrantLock reentrantLock) {
        this.threadName = threadName;
        this.reentrantLock = reentrantLock;
    }

    @Override
    public void run() {
        System.out.println("Thread " + threadName + " is waiting to get lock");
        reentrantLock.lock();
        try {
            System.out.println("Thread " + threadName + " acquired lock");
            getA();
        } finally {
            reentrantLock.unlock();
            System.out.println("Thread " + threadName + " released the lock and the lock held count is :"+reentrantLock.getHoldCount());
        }
    }

    public void getA() {
        System.out.println("getA :: Thread " + threadName + " is waiting to get lock");
        try {
            reentrantLock.lock();
            System.out.println("getA :: Thread " + threadName + " acquired lock");
            System.out.println("getA :: Lock count held by thread " + threadName + " : " + reentrantLock.getHoldCount());

        } finally {
            reentrantLock.unlock();
            System.out.println("getA :: Thread " + threadName + " released the lock and the lock held count is :"+reentrantLock.getHoldCount());
        }
    }
}


Output:

Thread Thread1 is waiting to get lock
Thread Thread1 acquired lock
getA :: Thread Thread1 is waiting to get lock
getA :: Thread Thread1 acquired lock
getA :: Lock count held by thread Thread1 : 2
getA :: Thread Thread1 released the lock and the lock held count is :1
Thread Thread1 released the lock and the lock held count is :0
Thread Thread2 is waiting to get lock
Thread Thread2 acquired lock
getA :: Thread Thread2 is waiting to get lock
getA :: Thread Thread2 acquired lock
getA :: Lock count held by thread Thread2 : 2
getA :: Thread Thread2 released the lock and the lock held count is :1
Thread Thread2 released the lock and the lock held count is :0

You can see lock held count should go back to 0 for another thread to acquire a lock.


You may also like to see


Advanced Java Multithreading Interview Questions & Answers

Type Casting Interview Questions and Answers In Java?

Exception Handling Interview Question-Answer

Method Overloading - Method Hiding Interview Question-Answer

How is ambiguous overloaded method call resolved in java?

Method Overriding rules in Java

Interface interview questions and answers in Java

Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.

How Comparable and Comparator works internally in Java

How Comparable and Comparator works internally in Java 


In Java, Comparable and Comparator are used for sorting collection of objects.

java.lang.Comparable is used to sort collection of same types(classes) like List<Student>, List<Employee>, List<Orange>, It means Comparable is like "I can compare myself with another object of same type".

Example: if we want to sort List<Student> based on roll number or their first name etc.

java.util.Comparator is used to sort collection of different types(classes) like List<Object>.
It means Comparator is like "I can compare myself with other object of same/different type"

If you have observe java.util.Comparator is more like a Utility class that can sort objects of any class you provide and that is why it is in util package. 


Comparable example


package com.javabypatel;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ComparableExample {

    private static final int INSERTIONSORT_THRESHOLD = 7;

    public static void main(String[] args) {
        Student s1 = new Student(10);
        Student s2 = new Student(50);
        Student s3 = new Student(20);
        Student s4 = new Student(30);

        List<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        System.out.println("Before sort:");
        list.forEach(s -> System.out.print(s.rollNo + " "));

        sort(list);
        //Collections.sort(list);

        System.out.println("After sort:");
        list.forEach(s -> System.out.print(s.rollNo + " "));
    }

    static void sort(List<Student> list) {
        int low = 0;
        Object[] dest = list.toArray();
        for (int i = 0; i < list.size(); i++)
            for (int j = i; j > low && ((Comparable) dest[j - 1]).compareTo(dest[j]) > 0; j--)
                swap(dest, j, j - 1);

        ListIterator<Student> i = list.listIterator();
        for (Object e : dest) {
            i.next();
            i.set((Student) e);
        }
    }

    private static void swap(Object[] x, int a, int b) {
        Object t = x[a];
        x[a] = x[b];
        x[b] = t;
    }

}

class Student implements Comparable<Student>{
    int rollNo;

    public Student(int rollNo) {
        this.rollNo = rollNo;
    }

    @Override
    public int compareTo(Student s) {
        if(rollNo==s.rollNo)
            return 0;
        else if(rollNo>s.rollNo)
            return 1;
        else
            return -1;
    }
}


Output:

Before sort:
10 50 20 30
After sort:
10 20 30 50

Here we are sorting List of Students by their roll number.
Generally we should be using "Collections.sort(list);" for sorting the list, for better understanding I have copied the code of sort method to understand how internally it sort the list.

It compare 2 objects and swap based on result returned by compareTo method.

Comparator example


package com.javabypatel;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparatorExample {

    public static void main(String[] args) {
        Student s1 = new Student(10, "Zara");
        Student s2 = new Student(50, "Jayesh");
        Student s3 = new Student(20, "Ash");
        Student s4 = new Student(30, "Kate");

        List<Student> list = new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);

        System.out.println("Before sort:");
        list.forEach(s -> System.out.print(s.name + " " + s.rollNo + ", "));

        NameComparator nameComparator = new NameComparator();
        Collections.sort(list, nameComparator);

        System.out.println("\n\nAfter sort by name:");
        list.forEach(s -> System.out.print(s.name + " " + s.rollNo + ", "));

        RollNumberComparator rollNumberComparator = new RollNumberComparator();
        Collections.sort(list, rollNumberComparator);

        System.out.println("\n\nAfter sort by Roll number:");
        list.forEach(s -> System.out.print(s.name + " " + s.rollNo + ", "));
    }
}


package com.javabypatel;

import java.util.Comparator;

public class Student {
    int rollNo;
    String name;

    public Student(int rollNo, String name) {
        this.rollNo = rollNo;
        this.name = name;
    }
}


//Name Comparator
class NameComparator implements Comparator<Student> {
    public int compare(Student s1, Student s2) {
        return s1.name.compareTo(s2.name);
    }
}

//Roll number Comparator 
class RollNumberComparator implements Comparator<Student> {
    public int compare(Student s1, Student s2) {
        if (s1.rollNo < s2.rollNo) return -1;
        if (s1.rollNo > s2.rollNo) return 1;
        else return 0;
    }
} 

Output: 
Before sort: 
Zara 10, Jayesh 50, Ash 20, Kate 30, 

After sort by name: 
Ash 20, Jayesh 50, Kate 30, Zara 10, 

After sort by Roll number: 
Zara 10, Ash 20, Kate 30, Jayesh 50,

You may also like to see


Level Order Traversal of Binary Tree.

Advanced Multithreading Interview Question-Answer

Traverse a Binary Tree in Level Order Traversal

Serialize and Deserialize a Binary Tree

Find diameter of Binary Tree

How Much Water Can a Bar Graph with different heights can Hold

Interview Question-Answer on Java

Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.

Java Memory Management Interview Questions

Java Memory Management Interview Questions  


What is memory leak?

In Java, Garbage collector handles memory management, but when garbage collector is not able to free any object that is not used by the application but it still holds the reference to it is called memory leak.
In other words, when the program/application allocates memory for the object and later when object is no longer needed, instead of marking the reference as null, application holds the indirect reference to that object in such a way that garbage collector cannot free that object is called memory leak. slowly, application memory starts growing and ultimately result in OutOfMemoryError.


What happens when Garbage Collector(GC) runs? what does it mean by "stop-the-world"?
When GC thread runs, other threads are stopped for that duration, so application waits for that duration.
Note: Irrespective of GC need to run in Old generation or New Generation, all the events of GC run will pause application threads until GC run completes.


In Java, what goes in Heap and Stack?

Heap and Stack both are the part of RAM. So there is a separate space in RAM for stack and heap. 
Local variables/references: All the local variables (primitive type) of the method and the method call itself goes to Stack. 

Objects: when an object is created using new operator, the actual space for that object is allocated in heap but the reference to that space(object) is created in stack.
class Student {
    String rollNumber;
    String name
    Address address;
}

class Address{
    String zipcode;
}
public static void main(String args[]){
   Student s1 = new Student(10, "Jason", new Address("V5H3U7"))
}


Stack                     Heap
s1 ----------------> Student{ rollNumber = 10, name="Jason", address}
                                                                                                     |
                                                                                                     |
                                                                              Address{zip code = "V5H3U7"}

What is the scope of Heap and Stack?

The stack is associated for a thread, so when the thread is done the stack is reclaimed. The heap is typically allocated at application startup by the runtime, and is reclaimed when the application (technically process) exits.


Which is faster Stack or Heap? Why?

Stack is faster in many terms than Heap though they both are part of RAM. 
For Stack, in terms of deletion, it just needs to move the pointers in LIFO Manner, whereas for Heap, it has to do checks for live references along with that deletion creates fragmentation issues where if memory is freed in non continuous manner, then it has to do compaction (Memory compaction is the process of moving allocated objects together and leaving empty space together.)

Heap is shared across Threads, so allocation/deallocation of memory needs to be synchronized for Heaps, but for Stack, memory is private to Stack. this is also the reason Stack is faster than Heap.

Stack is generally accessed more frequently so for that purpose data of Stack is cached and that is also the reason it is faster than Heap.

The heap is a portion on RAM which is not managed automatically, and is not as tightly managed by the CPU. It is a just a block of memory and need to be managed by user. To allocate memory on the heap, you must use new keyword. we are responsible for deallocation of unused memory once we no longer require it, failing which can cause memory leaks.



How you fine tune Heap size?


-Xms (example: -Xms64m or -Xms64M)
Sets the initial size of the Java heap. 

-Xmx (example: -Xmx1g or -Xmx1G)
Sets the maximum size to which the Java heap can grow. 

-Xmn (example: -Xmn512, -Xmn512m, -Xmn512k)
Sets the initial Java heap size for the Young generation(Eden generation). 

-Xss (example: -Xss512, -Xss512m, -Xss512k)
Sets the maximum stack size of each thread.
This option allows to fine tune max size allocated to each thread to store local variable, partial results and method calling information.
When the method is doing heavy operation with lots of variables, method calls and if you are encountering  StackOverflowError, you can fine tune stack size by using this flag.

-Xnoclassgc
Disables garbage collection (GC) of classes. When you specify -Xnoclassgc at startup, the class objects in the application will be left untouched during GC and will always be considered live. This can result in more memory being permanently occupied which, if not used carefully, will throw an out of memory exception.


When you encounter StackOverflowError and OutOfMemoryError?

StackOverflowError :
Stack is used in Java for method execution, for every method call, a block of memory is created in the stack. The data related to method like parameters, local variables or references to objects are stored in this block.

When the method finishes its execution, this block is removed from the stack along with data stored in it. If a method keep calling other method recursively without returning back then at one point Stack will be full and there would not be any space left for allocating new stack block at that time you will encounter StackOverflowError.

OutOfMemoryError:
When there is no space left for creating new objects on Heap memory, java.lang.OutOfMemoryError  is thrown.


OutOfMemoryError is encountered in below two scenarios, 
1. java.lang.OutOfMemoryError: Java heap space Issue
2. java.lang.OutOfMemoryError: PermGen space Issue

Note few points below: 
1. Garbage collection happens on Heap only.
2. Stack size is private to Thread
3. Heap size is shared across Threads.



How Garbage collection works, What is Mark and Sweep algorithm for garbage collection?  

In Java, GC handles memory management, so it is GC's job to remove the object and free up the heap space when it is no longer referenced.
For removing the object, it first need to scan all the objects present, whether there exist any active references to the object or not, and remove the object those are not referenced from anywhere.

  • The process of identifying and marking the referenced(reachable) object is called Marking phase, where GC starts marking the objects as a indication that they are reachable, that is, the object reference is being referred(in use) and should not be deleted.
  • The process of deleting the marked objects is called Sweep phase, where un-referenced objects  memory are freed up and heap space will be reclaimed. 



Does GC guarantees that a program will not run OutOfMemory?

GC does not guarantee that a program will not run out of memory. It is possible that Program create objects faster as compare to GC cleaning the unreferenced objects. Also, it is possible that application creates lots of heavy object and holding the references to those object in this case GC can't help and may cause OutOfMemory error.


How many Class loaders are present in JVM?

First of all what Class loader does is load the .class files from physical location to JVM's memory and stores information such as class names, parent class, methods, constructors etc.

There are mainly 3 class loaders present in JVM, 

Bootstrap ClassLoader: This classloader prime responsibility is to load internal core java classes present in the rt.jar and other classes present in the java.lang.* package. This class loader is shipped with every JVM and is written in native language. This class loader has no parent classloader.

Extension ClassLoader: This classloader responsibility is to load classes from jre\lib\ext folder.
The parent of this class loader is Bootstrap classloader. Java extensions are also referred to as optional packages.

Application or System ClassLoader: The parent of this class loader is Extension classloader  
and is responsible for loading the classes from the system classpath(generally classes folder). It internally uses the ‘CLASSPATH‘ environment variable and is written in Java language. 

Note: Class is loaded into memory only once even if you try to load multiple times.


When you get NoClassDefFoundError? 

It is an error of type java.lang.Error. Any class which is available while compilation phase but is no longer available while running the application causes NoClassDefFoundError. Example:
class Student{ }
public class MainApp{
    public static void main(String[] args){
        Student stud = new Student();
    }
}
> javac MainApp.java
Above command will generate 2 classes MainApp.class and Student.class
Delete Student.class file
> java MainApp
This will throw NoClassDefFoundError


When you get ClassNotFoundException? 

It is an runtime exception and is caused when application tries to explicitly load any class using Class.forName("path of class") and if the class is not available at the mentioned Path then it throws ClassNotFoundException.


How JVM Heap memory blocks is divided?
Till Java 7
java memory management and garbage collection
Java memory management

Eden space, S0, S1 = Young Generation
S0, S1 = Survivor Space
Old Memory = Old Generation = Tenured Memory
Perm = Permanent Generation

Short description of Heap blocks:

Eden space, S0 and S1 are called Young generation space and Old Memory space is called old Generation space this is because Newly created objects are places in Eden space.

When GC runs in Eden space and if there are live references found in Eden space they are placed into Survivor space S0 and when GC runs in S0 and the reference is still live
(after some threshold) it is placed in S1. Now when GC runs in S1 and the reference is still live (after some threshold of surviving multiple GC cycle) it is placed in Old generation space.

Permanent Generation Space (PermGen space):
This is non Heap space used to store class metadata information. It is used by JVM to describe the classes and methods used in the application.

Note: You can get OutOfMemoryError when any of this block has no further space to store data.

When GC runs at Eden, S0 or S1 space it is called Minor GC, but when it runs in Old Generation it is called Major GC and it takes time to complete GC operation in Old generation . 

Java 8
PermGen space which was part of Heap is removed in Java8 and is now called Metaspace.
The JDK 8 HotSpot JVM is now using native memory for the representation of class metadata, this also means that there will no longer be java.lang.OutOfMemoryError: PermGen space problems.

The arguments which was used to set the PermGen space is now useless and PermSize and MaxPermSize JVM arguments are ignored and a warning is given if present at start-up.

A new flag called MaxMetaspaceSize is provided to limit the amount of native memory used for class metadata. If we don’t specify this, the Metaspace will dynamically re-size depending of the application demand at runtime.

Garbage collection of the dead classes and classloaders is triggered once the class metadata usage reaches the “MaxMetaspaceSize”.



What is Method Area and where it belongs?

Method Area is part of space in the Perm Gen and used to store class structure (runtime constants and static variables) and code for methods and constructors.


Where is Java String pool located?

String pool was part of PermGen space but is now moved to separate Heap space because PermGen space was very limited, default size 64 MB and was used to store class metadata .class files information.


When are static variables loaded in memory ?

They are loaded at runtime when the respective Class is loaded.


What happens when we import any package or class? what if the same import is repeated in multiple classes? Will the JVM load the package or class twice at runtime?

No matter how many times you import the same class. JVM will load class only once(per class loader).


When is the finalize() method called in Java?

The finalize method will be called after the GC detects that the object is no longer reachable, and before it actually reclaims the memory used by the object.

Note: It is not a good practice to rely on finalize() method for clean up operation as we never know when GC will be invoked, also it is not guaranteed. 
Also, finalize method may not get called if there is always active reference to the object.
finalize() is part of Object class.
@Override
public void finalize() {
    try {
        reader.close();
        System.out.println("Closed BufferedReader in the finalizer");
    } catch (IOException e) {
        // ...
    }
}

there are chances that class A job is to read data from file and then cache the String and always returned cached value, in this case we only need to open connection to file, read it and close. if we use finalize for closing the connection would be bad here because class A instance may always have active reference to return the cached value and finalize for closing the file will never get invoked.



Do member(instance) and local(method) variables have default values?

Example:
public class Example {
    static int a;
    int b;

    void getA(){
        A ref;
        int c ;
        System.out.println(a);   // ok         
        System.out.println(b);   // ok         
        System.out.println(ref); //Error: Variable ref might not have been initialized            
        System.out.println(c);   //Error: Variable c might not have been initialized    
   }
}


All member variables have to load into heap so they have to initialized with default values when an instance of class is created, so member variables are initialized with default values.
Local variables are stored on stack, so they are not initialized by default.


When the class is loaded by classloader?

When the class object is created using the new operator (static class loading) or when the class is explicitly loaded using Class.forName("path of the class") (dynamic class loading).


What are strong, soft, weak and phantom references in Java?


These references are useful in terms of when they are eligible for Garbage collection.

Strong Reference:
This is the default behavior of object creation. Strong reference means the object should not be garbage collected if there is any live reference pointing to it.

Student s = new Student()
s.rollNo = 10;
                                                              GC
                                                             ---------------------------
s------------------------------------------->| Student(rollNo=10)  | Heap
                                                              --------------------------
                                                              GC will not remove this memory because it is referred by                
                                                               strong reference "s"    

Weak Reference:
A weak reference is a reference which is not strong enough to survive garbage collection. In simple words, as the name suggest, object created using weak reference will be weak enough to get removed when the next garbage collection cycle runs.

Soft Reference:
A soft reference is very similar to Weak reference but the only difference is GC will throw the soft reference only when memory is low. It is generally used for implementing Cache.

Phantom reference:
A phantom reference will be finalized but the memory will not be reclaimed. Can be useful when you want to be notified that an object is about to be collected.



What are different ways to create String object? Explain.

There are 2 ways to create String object,
1. String str1 = new String("javabypatel");
2. String str2 = "javabypatel";

With the first approach using new operator, JVM creates the String in Heap as well as in String literal Pool (However I found conflicting answers for this, where some claims that only one object is created in heap and we need to explicitly call intern() method to copy it to pool), str1 will refer to the object created in Heap.

When we create a String using double quotes, JVM looks in the String pool to find if any other String is stored with same value. If found, it just returns the reference to that String object else it creates a new String object with given value and stores it in the String pool.



How substring() method of String class use to create memory leaks before Java 7?

We know memory leak happens when application is not using a object and GC is not able to reclaim memory blocked by that object due to active reference still exist.
substring method creates scenario as described above which leads to Memory leak.

Detail explanation in this How substring method creates memory leak in Java



What is Just-in-time(JIT) compilation in Java?

1. In Java, .java files are compiled to byte code(.class file)
2. JVM reads the .class files and convert it into machine understandable format.
3. Machine understandable lines are passed to CPU for execution.

Example source code:
String str1 = "Hello, this is Java";
System.out.println(str1);
System.out.println(str1);
System.out.println(str1);

Above code is compiled and say .class file is generated like below,

xyz1111
mnooooo
mnooooo
mnooooo

JVM needs to load compiled .class file, converts each line into Machine understandable format and give it for execution.

Before converting the compiled .class files to machine understandable instructions, JVM takes the compiled class files and does further compilation for complex optimizations to generate high-quality machine code. we will see what kind of optimization it does later. (this further compilation is done by part of JVM which is known at JIT.)

From above example, is there need to convert byte code "mnooooo" 3 times?
No. converted code can be stored and can be reuse when required.

JIT Compiler helps doing such optimization for JVM.

JIT also does further compilation to .class files and one of the feature for which it does further compilation is inlining, which is the practice of substituting the body of a method into the places where that method is called. Inlining saves the cost of calling the method; no new stack frames need to be created. By default, Java HotSpot VM will try to inline methods that contain less than 35 bytes of JVM bytecode.

Loop optimization, type sharpening, dead-code elimination, and intrinsics are just some of the other ways that Java HotSpot VM tries to optimize code as much as it can. Techniques are frequently layered one on top of another, so that once one optimization has been applied, the compiler might be able to see more optimizations that can be performed.

Compilation Modes
Inside Java HotSpot VM, there are actually two separate JIT compiler modes, which are known as C1 and C2. C1 is used for applications where quick startup and rock-solid optimization are required; GUI applications are often good candidates for this compiler. C2, on the other hand, was originally intended for long-running, predominantly server-side applications. Prior to some of the later Java SE 7 releases, these two modes were available using the -client and -server switches, respectively.


When memory is allocated for static variables in java?

When the class is first loaded into memory.


Where does static method, variables are stored in Java?


Classes goes in special area on heap called Permanent Generation.
Static member variables are kept on the Permanent Generation.
Eg:
static int i =10 (i=10 goes in perm gen space.)

static Address address = new Address
(address = "pointer to where address object is created" address reference will be part of permgen space but the actual memory allocation [new Address()] can be in Young or Old generation in Heap.)

static method(code): There is only one copy of each method per class, be the method static or non-static. That copy is put in the Permanent Generation area. (Method Area part of PermGen space)

You may also like to see


Level Order Traversal of Binary Tree.

Advanced Multithreading Interview Question-Answer

Traverse a Binary Tree in Level Order Traversal

Serialize and Deserialize a Binary Tree

Find diameter of Binary Tree

How Much Water Can a Bar Graph with different heights can Hold

Interview Question-Answer on Java

Enjoy !!!! 

If you find any issue in post or face any error while implementing, Please comment.