Sunday, September 22, 2019

Multithreading | Concurrency Interview Questions (Along with JAVA 8 Enhancements)

1. How can a Java application access the current thread?



public class MainThread {

    public static void main(String[] args) {

        long id = Thread.currentThread().getId();

        String name = Thread.currentThread().getName();

        ...

    }

}



2. What properties does each Java thread have?

Each Java thread has the following properties:



an identifier of type long that is unique within the JVM

a name of type String

a priority of type int

a state of type java.lang.Thread.State

a thread group the thread belongs to



3. What states can a thread have and what is the meaning of each state?

4. Is it possible to start a thread twice?

No, after having started a thread by invoking its start() method, a second invocation of start() will throw an IllegalThreadStateException.

5. What is a daemon thread?

A daemon thread is a thread whose execution state is not evaluated when the JVM decides if it should stop or not. The JVM stops when all user threads (in contrast to the daemon threads) are terminated. Hence daemon threads can be used to implement for example monitoring functionality as the thread is stopped by the JVM as soon as all user threads have stopped:





public class Example {

    private static class MyDaemonThread extends Thread {

        public MyDaemonThread() {

            setDaemon(true);

        }

        @Override

        public void run() {

            while (true) {

                try {

                    Thread.sleep(1);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

    }

    public static void main(String[] args) throws InterruptedException {

        Thread thread = new MyDaemonThread();

        thread.start();

    }

}

The example application above terminates even though the daemon thread is still running in its endless while loop.



6.How to take Thread Dump



You can generate a thread dump under Unix/Linux by running kill -QUIT <pid>, and under Windows by hitting Ctl + Break



7. What are differences between wait() and sleep() method in Java?

wait():

wait() method releases the lock.

wait() is the method of Object class.

wait() is the non-static method – public final void wait() throws InterruptedException { //…}

wait() should be notified by notify() or notifyAll() methods.

wait() method needs to be called from a loop in order to deal with false alarm.

wait() method must be called from synchronized context (i.e. synchronized method or block), otherwise it will throw IllegalMonitorStateException

sleep():



sleep() method doesn’t release the lock.

sleep() is the method of java.lang.Thread class.

sleep() is the static method – public static void sleep(long millis, int nanos) throws InterruptedException { //… }

after the specified amount of time, sleep() is completed.

sleep() better not to call from loop(i.e. see code below).

sleep() may be called from anywhere. there is no specific requirement.



8.  What happens when an uncaught exception leaves the run() method?

I can happen that an unchecked exception escapes from the run() method. In this case the thread is stopped by the Java Virtual Machine. It is possible to catch this exception by registering an instance that implements the interface UncaughtExceptionHandler as an exception handler.



This is either done by invoking the static method Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler), which tells the JVM to use the provided handler in case there was no specific handler registerd on the thread itself, or by invoking setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler) on the thread instance itself.



9. What is the difference between the two interfaces Runnable and

Callable?



The interface Runnable defines the method run() without any return value whereas the interface Callable allows the method call() to return a value and to throw an exception.



10. What is a shutdown hook?

A shutdown hook is a thread that gets executed when the JVM shuts down. It can be registered by invoking addShutdownHook(Runnable) on the Runtime instance:



Runtime.getRuntime().addShutdownHook(new Thread() {

    @Override

    public void run() {

    }

});



11. Need for Callable



There are two ways of creating threads – one by extending the Thread class and other by creating a thread with a Runnable. However, one feature lacking in  Runnable is that we cannot make a thread return result when it terminates, i.e. when run() completes. For supporting this feature, the Callable interface is present in Java.



12. Callable vs Runnable



For implementing Runnable, the run() method needs to be implemented which does not return anything, while for a Callable, the call() method needs to be implemented which returns a result on completion. Note that a thread can’t be created with a Callable, it can only be created with a Runnable.

Another difference is that the call() method can throw an exception whereas run() cannot.



A Runnable, however, does not return a result and cannot throw a checked exception.



Method signature that has to overridden for implementing Callable.



public Object call() throws Exception;



13. Future

A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled.



Observe that Callable and Future do two different things – Callable is similar to Runnable, in that it encapsulates a task that is meant to run on another thread, whereas a Future is used to store a result obtained from a different thread. In fact, the Future can be made to work with Runnable as well, which is something that will become clear when Executors come into the picture.



 14. Shutting down exector



Finally, When you are done using the ExecutorService you should shut it down, so the threads do not keep running.



1

executor.shutdown();

For instance, if your application is started via a main() method and your main thread exits your application, the application will keep running if you have an active ExecutorService in your application. The active threads inside this ExecutorService prevents the JVM from shutting down.



To terminate the threads inside the ExecutorService you call its shutdown() method. The ExecutorService will not shut down immediately, but it will no longer accept new tasks, and once all threads have finished current tasks, the ExecutorService shuts down. All tasks submitted to the ExecutorService before shutdown() is called, are executed.



15.  Future Task Example :



CallableCalculater.java:


package com.jcg;

import java.util.concurrent.Callable;

/**
 * @author ashraf
 *
 */
public class CallableCalculater implements Callable {

    private long first;
    private long last;
    private long divisor;
   

    /**
     * Instantiates a new callable calculater.
     *
     * @param first the first
     * @param last the last
     * @param divisor the divisor
     */
    public CallableCalculater(long first, long last, long divisor) {
        this.first = first;
        this.last = last;
        this.divisor = divisor;
    }


    @Override
    public Long call() throws Exception {

        return Calculater.calculateNumberOfDivisible(first, last, divisor);
    }

}
CallableCalculater.java is wrapping the calculateNumberOfDivisible() of Calculater.java in a Callable task to be given to our FutureTask later on.

FutureTaskDemo.java:


package com.jcg;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

/**
 * @author ashraf
 *
 */
public class FutureTaskDemo {
   
    // Maximum number to check
    public static final long MAX_NUMBER = 3000000000l;
   
    // DIVISOR to be used in calculation
    private static final long DIVISOR = 3;

    /**
     * @param args
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public static void main(String[] args) {
       
        // Sequential execution
        System.out.println("Starting sequential execution ....");
        long timeStart = System.currentTimeMillis();
        long result = Calculater.calculateNumberOfDivisible(0, MAX_NUMBER, DIVISOR);
        long timeEnd = System.currentTimeMillis();
        long timeNeeded = timeEnd - timeStart;
        System.out.println("Result         : " + result + " calculated in " + timeNeeded + " ms");
       
       
        // Parallel execution
        System.out.println("Starting parallel execution ....");
        long timeStartFuture = System.currentTimeMillis();
       
        long resultFuture = 0;
       
        // Create a new ExecutorService with 2 thread to execute and store the Futures
        ExecutorService executor = Executors.newFixedThreadPool(2);
        List<FutureTask> taskList = new ArrayList<FutureTask>();

        // Start thread for the first half of the numbers
        FutureTask futureTask_1 = new FutureTask(new CallableCalculater(0, MAX_NUMBER / 2, DIVISOR));
        taskList.add(futureTask_1);
        executor.execute(futureTask_1);

        // Start thread for the second half of the numbers
        FutureTask futureTask_2 = new FutureTask(new CallableCalculater(MAX_NUMBER / 2 + 1, MAX_NUMBER, 3));
        taskList.add(futureTask_2);
        executor.execute(futureTask_2);

        // Wait until all results are available and combine them at the same time
        for (FutureTask futureTask : taskList) {
            try {
                resultFuture += futureTask.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
       
        // Shutdown the ExecutorService
        executor.shutdown();
       
        long timeEndFuture = System.currentTimeMillis();
        long timeNeededFuture = timeEndFuture - timeStartFuture;
        System.out.println("Result (Future): " + resultFuture + " calculated in " + timeNeededFuture + " ms");

    }

}


16.  Fork/Join Framework



The effective use of parallel cores in a Java program has always been a challenge. There were few home-grown frameworks that would distribute the work across multiple cores and then join them to return the result set. Java 7 has incorporated this feature as a Fork and Join framework.



Basically the Fork-Join breaks the task at hand into mini-tasks until the mini-task is simple enough that it can be solved without further breakups. It’s like a divide-and-conquer algorithm. One important concept to note in this framework is that ideally no worker thread is idle. They implement a work-stealing algorithm in that idle workers steal the work from those workers who are busy.



ForkJoinPool



The ForkJoinPool is basically a specialized implementation of ExecutorService implementing the work-stealing algorithm we talked about above. We create an instance of ForkJoinPool by providing the target parallelism level i.e. the number of processors as shown below:



ForkJoinPool pool = new ForkJoinPool(numberOfProcessors);



Where numberOfProcessors = Runtime.getRunTime().availableProcessors();



If you use a no-argument constructor, by default, it creates a pool of size that equals the number of available processors obtained using above technique.

Although you specify any initial pool size, the pool adjusts its size dynamically in an attempt to maintain enough active threads at any given point in time. Another important difference compared to other ExecutorService's is that this pool need not be explicitly shutdown upon program exit because all its threads are in daemon mode.



ForkJoinTask





This is an abstract class for creating tasks that run within a ForkJoinPool. The Recursiveaction and RecursiveTask are the only two direct, known subclasses of ForkJoinTask. The only difference between these two classes is that the RecursiveAction does not return a value while RecursiveTask does have a return value and returns an object of specified type.



In both cases, you would need to implement the compute method in your subclass that performs the main computation desired by the task.



The ForkJoinTask class provides several methods for checking the execution status of a task. The isDone() method returns true if a task completes in any way. The isCompletedNormally() method returns true if a task completes without cancellation or encountering an exception, and isCancelled() returns true if the task was cancelled. Lastly, isCompletedabnormally() returns true if the task was either cancelled or encountered an exception.



18 Example Implementations of Fork/Join Pool Framework

In this example, you will learn how to use the asynchronous methods provided by the ForkJoinPool and ForkJoinTask classes for the management of tasks. You are going to implement a program that will search for files with a determined extension inside a folder and its subfolders. The ForkJoinTask class you’re going to implement will process the content of a folder. For each subfolder inside that folder, it will send a new task to the ForkJoinPool class in an asynchronous way. For each file inside that folder, the task will check the extension of the file and add it to the result list if it proceeds.

The solution to above problem is implemented in FolderProcessor class, which is given below:

Implementation Sourcecode
FolderProcessor.java

package forkJoinDemoAsyncExample;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RecursiveTask;

public class FolderProcessor extends RecursiveTask<List<String>>
{
   private static final long serialVersionUID = 1L;
   //This attribute will store the full path of the folder this task is going to process.
   private final String      path;
   //This attribute will store the name of the extension of the files this task is going to look for.
   private final String      extension;

   //Implement the constructor of the class to initialize its attributes
   public FolderProcessor(String path, String extension)
   {
      this.path = path;
      this.extension = extension;
   }

   //Implement the compute() method. As you parameterized the RecursiveTask class with the List<String> type,
   //this method has to return an object of that type.
   @Override
   protected List<String> compute()
   {
      //List to store the names of the files stored in the folder.
      List<String> list = new ArrayList<String>();
      //FolderProcessor tasks to store the subtasks that are going to process the subfolders stored in the folder
      List<FolderProcessor> tasks = new ArrayList<FolderProcessor>();
      //Get the content of the folder.
      File file = new File(path);
      File content[] = file.listFiles();
      //For each element in the folder, if there is a subfolder, create a new FolderProcessor object
      //and execute it asynchronously using the fork() method.
      if (content != null)
      {
         for (int i = 0; i < content.length; i++)
         {
            if (content[i].isDirectory())
            {
               FolderProcessor task = new FolderProcessor(content[i].getAbsolutePath(), extension);
               task.fork();
               tasks.add(task);
            }
            //Otherwise, compare the extension of the file with the extension you are looking for using the checkFile() method
            //and, if they are equal, store the full path of the file in the list of strings declared earlier.
            else
            {
               if (checkFile(content[i].getName()))
               {
                  list.add(content[i].getAbsolutePath());
               }
            }
         }
      }
      //If the list of the FolderProcessor subtasks has more than 50 elements,
      //write a message to the console to indicate this circumstance.
      if (tasks.size() > 50)
      {
         System.out.printf("%s: %d tasks ran.\n", file.getAbsolutePath(), tasks.size());
      }
      //add to the list of files the results returned by the subtasks launched by this task.
      addResultsFromTasks(list, tasks);
      //Return the list of strings
      return list;
   }

   //For each task stored in the list of tasks, call the join() method that will wait for its finalization and then will return the result of the task.
   //Add that result to the list of strings using the addAll() method.
   private void addResultsFromTasks(List<String> list, List<FolderProcessor> tasks)
   {
      for (FolderProcessor item : tasks)
      {
         list.addAll(item.join());
      }
   }

   //This method compares if the name of a file passed as a parameter ends with the extension you are looking for.
   private boolean checkFile(String name)
   {
      return name.endsWith(extension);
   }
}
And to use above FolderProcessor, follow below code:

Main.java

package forkJoinDemoAsyncExample;

import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

public class Main
{
   public static void main(String[] args)
   {
      //Create ForkJoinPool using the default constructor.
      ForkJoinPool pool = new ForkJoinPool();
      //Create three FolderProcessor tasks. Initialize each one with a different folder path.
      FolderProcessor system = new FolderProcessor("C:\\Windows", "log");
      FolderProcessor apps = new FolderProcessor("C:\\Program Files", "log");
      FolderProcessor documents = new FolderProcessor("C:\\Documents And Settings", "log");
      //Execute the three tasks in the pool using the execute() method.
      pool.execute(system);
      pool.execute(apps);
      pool.execute(documents);
      //Write to the console information about the status of the pool every second
      //until the three tasks have finished their execution.
      do
      {
         System.out.printf("******************************************\n");
         System.out.printf("Main: Parallelism: %d\n", pool.getParallelism());
         System.out.printf("Main: Active Threads: %d\n", pool.getActiveThreadCount());
         System.out.printf("Main: Task Count: %d\n", pool.getQueuedTaskCount());
         System.out.printf("Main: Steal Count: %d\n", pool.getStealCount());
         System.out.printf("******************************************\n");
         try
         {
            TimeUnit.SECONDS.sleep(1);
         } catch (InterruptedException e)
         {
            e.printStackTrace();
         }
      } while ((!system.isDone()) || (!apps.isDone()) || (!documents.isDone()));
      //Shut down ForkJoinPool using the shutdown() method.
      pool.shutdown();
      //Write the number of results generated by each task to the console.
      List<String> results;
      results = system.join();
      System.out.printf("System: %d files found.\n", results.size());
      results = apps.join();
      System.out.printf("Apps: %d files found.\n", results.size());
      results = documents.join();
      System.out.printf("Documents: %d files found.\n", results.size());
   }
}
Output of above program will look like this:

Main: Parallelism: 2
Main: Active Threads: 3
Main: Task Count: 1403
Main: Steal Count: 5551
******************************************
******************************************
Main: Parallelism: 2
Main: Active Threads: 3
Main: Task Count: 586
Main: Steal Count: 5551
******************************************
System: 337 files found.
Apps: 10 files found.
Documents: 0 files found.

How it works?
In the FolderProcessor class, Each task processes the content of a folder. As you know, this content has the following two kinds of elements:

Files
Other folders
If the task finds a folder, it creates another Task object to process that folder and sends it to the pool using the fork() method. This method sends the task to the pool that will execute it if it has a free worker-thread or it can create a new one. The method returns immediately, so the task can continue processing the content of the folder. For every file, a task compares its extension with the one it’s looking for and, if they are equal, adds the name of the file to the list of results.

Once the task has processed all the content of the assigned folder, it waits for the finalization of all the tasks it sent to the pool using the join() method. This method called in a task waits for the finalization of its execution and returns the value returned by the compute() method. The task groups the results of all the tasks it sent with its own results and returns that list as a return value of the compute() method.





19. Difference between Fork/Join Framework And ExecutorService



The main difference between the Fork/Join and the Executor frameworks is the work-stealing algorithm. Unlike the Executor framework, when a task is waiting for the finalization of the sub-tasks it has created using the join operation, the thread that is executing that task (called worker thread ) looks for other tasks that have not been executed yet and begins its execution. By this way, the threads take full advantage of their running time, thereby improving the performance of the application.



Existing Implementations in JDK

There are some generally useful features in Java SE which are already implemented using the fork/join framework.



1) One such implementation, introduced in Java SE 8, is used by the java.util.Arrays class for its parallelSort() methods. These methods are similar to sort(), but leverage concurrency via the fork/join framework. Parallel sorting of large arrays is faster than sequential sorting when run on multiprocessor systems.



2) Parallelism used in Stream.parallel(). Read more about this parallel stream operation in java 8.





20.  JAVA 8 Enhancements



Java JDK8 included the big fat interface called CompletionStage in the java.util.concurrent package. The same package also contains CompletableFuture which is a library implementation of CompletionStage. In this post we would see how CompletionStage and CompletableFuture provide piped asynchronous API thus enhancing reactive programming support in Java at the platform level.





21. CompletableFuture



CompletableFuture is a concrete implementation of a CompletionStage and it also implements the java.util.concurrent.Future interface as well. This is the class which models a task (which may or may not be asynchronous) and exposes various methods to interact with the task; for instance, we have methods to check if the task has completed; whether it has completed exceptionally; we even have APIs to chain dependencies between multiple tasks; cancelling uncompleted tasks, so on and so forth. We would be looking into some of these APIs soon.





A CompletableFuture can be instantiated and related methods can be called upon it, and we will see this in action in the subsequent section. However, there are convenient, static overloaded factory methods which provides further flexibility so that rather than worrying about harnessing CompletableFuture for a task, we can just concentrate on the task itself. I will explain this in a bit, but lets quickly have a look at the overloaded factory methods that I am talking about:

CompletableFuture supplyAsync() API


public static CompletableFuture supplyAsync(Supplier supplier)
public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)
java.util.function.Supplier is a functional interface which accepts nothing and “supplies” an output. The supplyAsync() API expects that a result-producing task be wrapped in a Supplier instance and handed over to the supplyAsync() method, which would then return a CompletableFuture representing this task. This task would, by default, be executed with one of the threads from the standard java.util.concurrent.ForkJoinPool (public static ForkJoinPool commonPool()).

However, we can also provide custom thread pool by passing a java.util.concurrent.Executor instance and as such the Supplier tasks would be scheduled on threads from this Executor instance.

So to sum up the, the easiest way of using CompletableFuture API is to wrap the task you want to execute in a Supplier – you may additionally supply an Executor service as needed – and hand it over to the supplyAsync() method which would return you the CompletableFuture!

There is yet another variant API available for retrieving a CompletableFuture. Notice that while discussing supplyAsync() I wrote that this is to be used when task would be result-bearing, in other words, when we expect the task to return back some output. However, in all cases where the task might not return any output, we may use the runAsyn() API, instead:

CompletableFuture runAsync() API


public static CompletableFuture runAsync(Runnable runnable)
public static CompletableFuture runAsync(Runnable runnable, Executor executor)
Notice that runAsync() expects a java.lang.Runnable instance, and we know that Runnable.run() does not return any result! This is the reason that the returned CompletableFuture type erases itself to Void type.



22. Completing the CompletableFuturer manually



A CompletableFuture can be instantiated through its no-arg constructor. And then we can manually provide a Runnable instance to a custom thread; and then CompletableFuture API provides complete method using which the CompletableFuture can be manually completed:

How to manually complete a CompletableFuture


//1. Why named CompletableFuture?
        CompletableFuture completableFuture1 = new CompletableFuture();
        new Thread (()-> {
            try {
                Thread.sleep(4000L);
            } catch (Exception e) {
                completableFuture1.complete(-100.0);
            }
            /*
             * we can manually "complete" a CompletableFuture!!
             * this feature is not found with the classical Future interface
             */
            completableFuture1.complete(100.0);
        },"CompFut1-Thread").start();
       
        System.out.println("ok...waiting at: "+new Date());
        System.out.format("compFut value and received at: %f, %s \n", completableFuture1.join(), new Date());


23. More cases of Completable future



https://www.callicoder.com/java-8-completablefuture-tutorial/



https://examples.javacodegeeks.com/core-java/util/concurrent/completablefuture/java-completionstage-completablefuture-example/

Very Good Article for Completable future :

https://netjs.blogspot.com/2018/11/completablefuture-in-java-with-examples.html


24.

Lambda Expression Java 8 - Interview Questions

1. for (int i = 0; i < n; i++) {
    new Thread(() -> System.out.println(i)).start();
        // Error—cannot capture i
}
The lambda expression tries to capture i, but this is not legal because i changes. There is no single value to capture. The rule is that a lambda expression can only access local variables from an enclosing scope that are effectively final. An effectively final variable is never modified—it either is or could be declared as final.

2. http://www.lambdafaq.org/what-are-the-reasons-for-the-restriction-to-effective-immutability/

3. Why the restriction on local variable capture?
Capture of local variables is restricted to those that are effectively final. Lifting this restriction would present implementation difficulties, but it would also be undesirable; its presence prevents the introduction of a new class of multithreading bugs involving local variables. Local variables in Java have until now been immune to race conditions and visibility problems because they are accessible only to the thread executing the method in which they are declared. But a lambda can be passed from the thread that created it to a different thread, and that immunity would therefore be lost if the lambda, evaluated by the second thread, were given the ability to mutate local variables. Even the ability to read the value of mutable local variables from a different thread would introduce the necessity for synchronization or the use of volatile in order to avoid reading stale data.

An alternative way to view this restriction is to consider the use cases that it discourages. Mutating local variables in idioms like this:

int sum = 0;
list.forEach(e -> { sum += e.size(); }); // illegal; local variable 'sum' is not effectively final
frustrates a principal purpose of introducing lambdas. The major advantage of passing a function to the forEach method is that it allows strategies that distribute evaluation of the function for different arguments to different threads. The advantage of that is lost if these threads have to be synchronized to avoid reading stale values of the captured variable.

The restriction of capture to effectively immutable variables is intended to direct developers’ attention to more easily parallelizable, naturally thread-safe techniques. For example, in contrast to the accumulation idiom above, the statement

int sum = list.map(e -> e.size()).reduce(0, (a, b) -> a+b);
creates a pipeline in which the results of the evaluations of the map method can much more easily be executed in parallel, and subsequently gathered together by the reduce operation.

The restriction on local variables helps to direct developers using lambdas aways from idioms involving mutation; it does not prevent them. Mutable fields are always a potential source of concurrency problems if sharing is not properly managed; disallowing field capture by lambda expressions would reduce their usefulness without doing anything to solve this general problem.

4. What is the type of a lambda expression?
A lambda expression is an instance of a functional interface. But a lambda expression itself does not contain the information about which functional interface it is implementing; that information is deduced from the context in which it is used. For example, the expression

    x -> 2 * x
can be an instance of the functional interface

    interface IntOperation { int operate(int i); }
so it is legal to write

    IntOperation iop = x -> x * 2;
The type expected for the expression on the right-hand side of the assignment here is IntOperation. This is called the target type for the lambda expression. Clearly a lambda expression can be type-compatible with different functional interfaces, so it follows that the same lambda expression can have different target types in different contexts. For example, given an interface

    interface DoubleOperation { double operate(double i); }
it would also be legal to write

    DoubleOperation dop = x -> x * 2;
The target type for a lambda expression must be a functional interface and, to be compatible with the target type, the lambda expression must have the same parameter types as the interface’s function type, its return type must be compatible with the function type, and it can throw only exceptions allowed by the function type.

From Java 8 onwards, lambda expressions can be used to represent the instance of a functional interface.


5. What is a functional interface?
Informally, a functional interface is one whose type can be used for a method parameter when a lambda is to be supplied as the actual argument. For example, the forEach method on collections could have the following signature:

    public void forEach(Consumer<? super T> consumer);
The implementation of forEach must apply a single method of the Consumer instance that has been supplied. This instance may be a lambda expression (see What is the type of a lambda expression?); if so, it will be applied in the place of that method. A lambda expression supplied in this way can take the place of only one interface method, so an interface can be used like this without ambiguity only if it has a single method.

More precisely, a functional interface is defined as any interface that has exactly one explicitly declared abstract method. (The qualification is necessary because an interface may have non-abstract default methods.) This is why functional interfaces used to be called Single Abstract Method (SAM) interfaces, a term that is still sometimes seen.

Examples
The following interfaces in the platform libraries (chosen from many) are functional interfaces according to the definition above:

    public interface Runnable { void run(); }
    public interface Callable<V> { V call() throws Exception; }
    public interface ActionListener { void actionPerformed(ActionEvent e); }
    public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }
Syntax notes
The interface Comparator is functional because although it declares two abstract methods, one of these—equals— has a signature corresponding to a public method in Object. Interfaces always declare abstract methods corresponding to the public methods of Object, but they usually do so implicitly. Whether implicitly or explicitly declared, such methods are excluded from the count.
[Skip this note on a first reading.] The situation is complicated by the possibility that two interfaces might have methods that are not identical but are related by erasure. For example, the methods of the two interfaces
    interface Foo1 { void bar(List<String> arg); }
    interface Foo2 { void bar(List arg); }
are said to be override-equivalent. If the (functional) superinterfaces of an interface contain override-equivalent methods, the function type of that interface is defined as a method that can legally override all the inherited abstract methods. In this example, if

    interface Foo extends Foo1, Foo2 {}
then the function type of Foo is

    void bar(List arg);
In fact, every functional interface has such a function type, though in the more common and simpler case it is just the single abstract method of that interface.


6. Why can’t default methods override equals, hashCode, and toString?
An interface cannot provide a default implementation for any of the methods of the Object class. This is a consequence of the “class wins” rule for method resolution: a method found on the superclass chain always takes precedence over any default methods that appear in any superinterface. In particular, this means one cannot provide a default implementation for equals, hashCode, or toString from within an interface.

This seems odd at first, given that some interfaces actually define their equals behavior in documentation. The List interface is an example. So, why not allow this?

One reason is that it would become more difficult to reason about when a default method is invoked. The current rules are simple: if a class implements a method, that always wins over a default implementation. Since all instances of interfaces are subclasses of Object, all instances of interfaces have non-default implementations of equals, hashCode, and toString already. Therefore, a default version of these on an interface is always useless, and it may as well not compile.

Another reason is that providing default implementations of these methods in an interface is most likely misguided. These methods perform computations over the object’s state, but the interface, in general, has no access to state; only the implementing class has access to this state. Therefore, the class itself should provide the implementations, and default methods are unlikely to be useful.

For further reading, see this explanation written by Brian Goetz in response to “Allow default methods to override Object’s methods” on the lambda-dev mailing list in March, 2013.


7. Conflict resolutions in Functional Interfaces

https://www.javabrahman.com/java-8/java-8-multiple-inheritance-conflict-resolution-rules-and-diamond-problem/

8. https://www.javabrahman.com/category/java-8/

Advance Interview Questions

1. DataStructure for Elevator Mechanism

JAVA Interview Questions- Core Java + General Questions

1. Describe SOLID principles.
2. Define some Design Patterns you have worked upon?
3. Difference between green thread and native thread in Java?
Green threads refers to a model in which the Java virtual machine itself creates, manages, and context switches all Java threads within one operating system process. No operating system threads library is used.
Native threads refers to a in which the Java virtual machine creates and manages Java threads using the operating system threads library – named libthread on UnixWare – and each Java thread is mapped to one threads library thread.

4. Why String is special in JAVA?
5. What are immutable classes and how to make a class immutable.
6. Why other classes are not Immutable?
7. Does static break encapsulation in Java?

static breaks encapsulation rule because it is possible to access it without settters or getters but directly. If you declare a variable like this : public static or static, when calling it from another class you can write : object.variable = value;.

8. Where are the variables of interface getting stored.

9. what is the difference between : String s="sid" and String s=new ("Sid");

Both expression gives you String object, but there is subtle difference between them. When you create String object using new() operator, it always create a new object in heap memory. On the other hand, if you create object using String literal syntax e.g. "a", it may return an existing object from String pool (a cache of String object in Perm gen space, which is now moved to heap space in recent Java release), if it's already exists. Otherwise it will create a new string object and put in string pool for future re-use.

Also :

new String("text"); explicitly creates a new and referentially distinct instance of a String object; String s = "text"; may reuse an instance from the string constant pool if one is available.

You very rarely would ever want to use the new String(anotherString) constructor. From the API:

String(String original) : Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since strings are immutable.

String s = "a";
String q = "a";
String w = new String("a");
String w1 = new String("a");

System.out.println(s == q);
System.out.println(s == w);
System.out.println(w1 == w);

Output :
true
false
false

w/w1 is then lost (eligible for GC) if later unused. String literals on the other hand are reused.

10 What and where is string constant pool? where are int stored in memory.

11. How is + overrided for string in java? ex : StringBuffer s="hi".append(s1).append(s2); and
String x=s+s1+s2? how many objects are being created in both cases.

Strings computed by constant expressions are computed at compile time and then
treated as if they were literals.
Specs : here

String s="Sachin"+" Tendulkar";
So in the case you have specified only one String literal will be created(created at compile time itself) and that is "SachinTendulkar". So there will be only one interned String in the String pool.

In case you try to concatenate separate explicit literals then only you will have separate interned Objects in the String pool. Eg.

String s1 = "Sachin";
String s2 = "Tendulkar";
String s3 = s1 + s2;
In above case you will have 3 different interned Objects in String pool.


12. Level Order traversal?
13. Improvements in hashmap in java 8?
14. treeify time complexity.
15. What is better HashSet or HashMap for getting distinct list of items? Consider Hashset internally implements HashMap.
16. How does Spring work internally?
17. Memory management in Java 8.
18 Give an example of Memory Leak and Out Of memory error.
19 Java is Pass by Value or Pass by reference.
Java is Pass by Value

20. Stored Areas Of Static, Instance & Local Variables

class HackTheJava
{
    static int i=0;     //Static Variable
    int j=0;            //Instance Variable
   
    void properties()
    {
        int k=0;        //Local Variable
        return ;
    }
}

All static & instance variables are stored in PermGen space of heap memory. If variables are primitive type then its value as well stored with them as name-value pair. But if variable is user-defined(objects) then its reference is stored in PermGen as name-reference pair but actually it is stored in other heap spaces like Young/Old Generation.

But Local Variables are stored in Stack of its corresponding thread. Similarly method calls are also stored in stack. So each thread has separate copy of local variables.Know more about Memory Allocation.


Saturday, September 21, 2019

Java hashCode() and equals() – Contract, rules and best practices

1. Contract b/w them
2. Special Attention When Using in ORM

Collection Interview Questions (With Java 8 Enhancements) - Part 4 Map Interface

1. What are IdentityHashMap and WeakHashMap?
2. Explain ConcurrentHashMap? How it works?
3. How hashmap works?
4. How to design a good key for hashmap?
5. When to use HashMap or TreeMap?
6. Difference between HashMap and HashTable?
7. Difference between HashMap and ConcurrentHashMap
8. Difference between ConcurrentHashMap and Collections.synchronizedMap( HashMap )
9. Difference between HashTable and Collections.synchronized(HashMap)
So far you must have got the core idea of the similarities between them. Both are synchronized version of collection. Both have synchronized methods inside class. Both are blocking in nature i.e. multiple threads will need to wait for getting the lock on instance before putting/getting anything out of it.

So what is the difference. Well, NO major difference for above said reasons. Performance is also same for both collections.

Only thing which separates them is the fact HashTable is legacy class promoted into collection framework. It got its own extra features like enumerators.

10. How HashMap works in Java
11. [Update] HashMap improvements in Java 8
As part of the work for JEP 180, there is a performance improvement for HashMap objects where there are lots of collisions in the keys by using balanced trees rather than linked lists to store map entries. The principal idea is that once the number of items in a hash bucket grows beyond a certain threshold, that bucket will switch from using a linked list of entries to a balanced tree. In the case of high hash collisions, this will improve worst-case performance from O(n) to O(log n).

Basically when a bucket becomes too big (currently: TREEIFY_THRESHOLD = 8), HashMap dynamically replaces it with an ad-hoc implementation of the treemap. This way rather than having pessimistic O(n) we get much better O(log n).

Bins (elements or nodes) of TreeNodes may be traversed and used like any others, but additionally support faster lookup when overpopulated. However, since the vast majority of bins in normal use are not overpopulated, checking for the existence of tree bins may be delayed in the course of table methods.

Tree bins (i.e., bins whose elements are all TreeNodes) are ordered primarily by hashCode, but in the case of ties, if two elements are of the same “class C implements Comparable<C>“, type then their compareTo() method is used for ordering.

Because TreeNodes are about twice the size of regular nodes, we use them only when bins contain enough nodes. And when they become too small (due to removal or resizing) they are converted back to plain bins (currently: UNTREEIFY_THRESHOLD = 6). In usages with well-distributed user hashCodes, tree bins are rarely used.


Collection Interview Questions (With Java 8 Enhancements) - Part 3 Set Interface


1. Set Interface - Specialty & Implementations ?

Set is a unique collections of objects.It does not store duplicate objects.

Implementations :  EnumSet, HashSet, LinkedHashSet, TreeSet.

HashSet , backed by a hash table (actually a HashMap instance), is the best performing implementation, but it does not maintain order.
TreeSet is backed by red-black tree and store elements in sorted order.It is slower than HashSet.
LinkedHashSet is backed by HashTable with LinkedList running through it, so it also maintains the order of insertion.

2. Collection operation

Set<String> set =people.stream().filter(x -> x!=null).collect(Collectors.toCollection(TreeSet::new));

3. Can Set Store null values?
You can add null value, but while accessing it will give you Null Pointer Exception. 

Set<String> a1 = new HashSet<>();
Set<String> b1 = new TreeSet<>();
a1.add(null);
b1.add(null);
System.out.println(a1);
System.out.println(b1);

Output :
Exception in thread "main" java.lang.NullPointerException

4. How HashSet store elements?

You must know that HashMap store key-value pairs, with one condition i.e. keys will be unique. HashSet uses Map’s this feature to ensure uniqueness of elements. In HashSet class, a map declaration is as below:
private transient HashMap<E,Object> map;

//This is added as value for each key
private static final Object PRESENT = new Object();
So when you store a element in HashSet, it stores the element as key in map and “PRESENT” object as value. (See declaration above).
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

5. Can a null element added to a TreeSet or HashSet?

As you see, There is no null check in add() method in previous question. And HashMap also allows one null key, so one “null” is allowed in HashSet.

TreeSet uses the same concept as HashSet for internal logic, but uses NavigableMap for storing the elements.

private transient NavigableMap<E,Object> m;

// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
NavigableMap is subtype of SortedMap which does not allow null keys. So essentially, TreeSet also does not support null keys. It will throw NullPointerException if you try to add null element in TreeSet.