April 01, 2016

Part 7: Java Thread Interview Questions & Answers (Thread Pool, Executor)

What is ThreadLocal variable in Java?
  • ThreadLocal in Java is introduced on JDK 1.2 but it later generified in JDK 1.4 to introduce type safety on ThreadLocal variable.
  • Like instance variable is per instance, ThreadLocal variable is per thread. Since class is expensive, its not good to use it in local scope, which requires separate instance on each invocation.
  • ThreadLocal can be associated with Thread scope, all the code which is executed by Thread has access to ThreadLocal variables but two thread can not see each others ThreadLocal variable.
  • Each thread holds an exclusive copy of ThreadLocal variable which becomes eligible to Garbage collection after thread finished or died, normally or due to any Exception, Given those ThreadLocal variable doesn't have any other live references.
  • ThreadLocal variables in Java are generally private static fields in Classes and maintain its state inside Thread.
  • e.g private static final ThreadLocal < SimpleDateFormat > dateformatter = new ThreadLocal < SimpleDateFormat > ()
What is the difference between Runnable and Callable in Java?
1. Runnable is there from JDK 1.0 while Callable was added on JDK 1.5.
2. Runnable interface has run() method to define task while Callable interface uses call() method for task definition.
3. run() method does not return any value, it's return type is void while call method returns  java.lang.Object type. The Callable interface is a generic parameterized interface and Type of value is provided when an instance of Callable implementation is created.
4. One more difference is that the Callable interface can throw checked exception, while Runnable can't [run() does not throw any checked exception)

What is thread pool?
We all know, creating a thread is expensive in terms of time and resource. If we create thread at time of request processing it will slow down our response time, also there is only a limited number of threads a process can create.

A Thread Pool gives us an option to avoid these issues. When a application starts-up, a pool of threads are created and the threads are reused for request processing. This pool of thread is known as 'thread pool' and threads are known as 'worker thread'.

Why thread pool uses Blocking Queue?
A Blocking Queue, is the special type of Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.

Whenever we submit/ execute a new task using the ExecutorService, the ExecutorService will internally stores the tasks in the queue. All the threads  available in the thread pool will perform two steps: 1). fetch the next task from the queue, 2). execute it. Since all the threads  available in thread pool will attempts to take the task from the queue and execute it at the same time (i.e concurrently), a queue which is thread safe is needed. That's the reason thread pool uses Blocking queue.

BlockingQueue works on following rules:
  • If fewer than poolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
  • If poolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
  • If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
What is the ideal thread pool size?
One Java thread corresponds to one OS thread. If we have a CPU with 5 cores, then at a time we can have only 5 threads running. That means, no matter how many threads you create via thread pool, only 5 threads will be executed at a time (time split scheduling). That means having too many threads is not particularly a good idea, when we have CPU intensive operations. In this case, no. of thread pool size = no. of core's in the CPU.

We can get no. of Core's in the CPU from Runtime.getRuntime().availableProcessors(). e.g:
public class ThreadTest {
    public static void main(String[] args) {
        //get count of cores available in CPU
        int coreCount=Runtime.getRuntime().availableProcessors();
        ExecutorService service=Executors.newFixedThreadPool(coreCount);

        for (int i=0; i<50 br="" i="">        {
            service.execute(new CpuIntensiveTask());
        }
    }

    static class CpuIntensiveTask implements Runnable
    {
        public void run()
        {
            System.out.println("******running..");
            try {
            Thread.sleep(1000);
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}


Now, let's take an example where the task has an IO intensive operation (e.g fetching data from the database or a task to call a REST API to get the data), then we can have size of the pool which is greater than no. of core's in CPU.

Why? Because in this case, the task will have to wait till the response is received (may be from REST API or from the DB), threads will remain in waiting state until a response is received. So, even though we have 'x' no. of core's in CPU, there no points of having 'x' threads because all the threads might be in waiting state for the operation to finish and there are no threads to fetch and execute the next task.

In short:
  • If the task type is CPU intensive: Ideal pool size= CPU core count. If the CPU is running other applications your application might not get access to all the Core's of the CPU.
  • If the task type is IO intensive Ideal pool size should be high. The pool size depend on the rate the task submissions and average task wait time. Too many threads will increase memory consumption too.
What are Executor, Executorservice and ScheduledExecutorService?
  • These interfaces are present in  java.util.concurrent package.
  • ExecutorService, and Executers are part of Java's Executor framework which provides thread pool facilities. 
  • Till Java 1.5, it was application developer's responsibility to create and manage such thread pool, but from JDK 5 onward Executor framework provides a variety of built-in thread pools in Java e.g. fixed thread pool which contains a fixed number of threads and cached thread pool which can spawn new threads when needed.
  • Executer interface is the parent, which is extended by ExecutorService.
  • Executor has execute() method which accepts an object of the Runnable interface, while submit() method of ExecutorService can accept objects of both Runnable and Callable interfaces.
  • execute() method doesn't return any result, its return type is void, while but submit() method returns the result of computation via a Future object.
  • Apart from allowing a client to submit a task, ExecutorService also provides methods to control the thread pool e.g. terminate the thread pool by calling the shutDown() method.
  • Executors class provides factory methods to create different kinds of thread pools e.g. newSingleThreadExecutor() creates a thread pool of just one thread, newFixedThreadPool(int numOfThreads) creates a thread pool of fixed number of threads and newCachedThreadPool() creates new threads when needed but reuse the existing threads if they are available.
  • ScheduledExecutorService is a sub-interface of ExecutorService, to execute commands periodically or after a given delay.
How to terminate a thread in Executor Framework in java?
  • When you are done using the ExecutorService you should shut it down, so the threads do not keep running. e.g, 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 ExexutorService 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.
  • If you want to shut down the ExecutorService immediately, you can call the shutdownNow() method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks. There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end. It is a best effort attempt.
What are the Lifecycle Methods of ExecutorService?
  • submit extends base method Executor.execute(java.lang.Runnable) by creating and returning a Future that can be used to cancel execution and/or wait for completion.
  • Methods invokeAny and invokeAll execute a collection of tasks and then wait for at least one, or all, to complete, respectively. 
  • shutdown() and shutdownNow(): An ExecutorService can be shut down, which will cause it to reject new tasks. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to even stop currently executing tasks. Tasks submitted to an ExecutorService after it has been shut down are handled by the rejected execution handler, which  might  discard  the  task  or  might  cause  execute  to  throw  the  unchecked RejectedExecutionException. 
  • awaitTermination(): Once  all  tasks  have  completed, the  ExecutorService  transitions  to  the  terminated state. The awaitTermination(long timeout, TimeUnit unit) method blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted.
  • isShutdown() and isTerminated(): These methods returns true if this executor has been shut down or if executor is in terminated state, respectively.
What is the difference between Executor.submit() and Executor.execute() method in Java?
  • Both methods are used to submit a task to thread pools. 
  • execute(Runnable runnnableObj) is defined in Executor interface and executes given task in future, but more importantly, it does not return anything (because the return type is void).
  • On other hand submit() is an overloaded method, it can take either Runnable or Callable task and can return Future object which can hold the pending result of computation. This method is defined on ExecutorService interface, which extends Executor interface, and every other thread pool class e.g. ThreadPoolExecutor or ScheduledThreadPoolExecutor gets these methods.
Difference between a Thread and an Executor in Java?
  • java.lang.Thread is a class in Java while java.util.concurrent.Executor is an interface.
  • The Executor allows your task is to be executed by a worker thread from the thread pool, while Thread itself execute your task.
  • Executor provides a execute() method which accepts a Runnable task, while Thread accepts the Runnable task on its constructor.
  • Thread can only execute one Runnable task but an Executor can execute any number of Runnable task.
  • In the case of a thread, it's developer's responsibility to create and start the thread, but in the case of Executor, the framework will create and start threads for you.
e.g:
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class ThreadTest {
public static void main(String args[]) {
Runnable runTask = new Runnable() {
@Override
public void run() {
System.out.println("Runnable task is executed by :"+Thread.currentThread().getName());
}
};
Thread newthread = new Thread(runTask, "NewThread");
newthread.start();
Executor e = Executors.newSingleThreadExecutor();
e.execute(runTask);
}
}

What are the types of thread pools available in Java?
1). FixedThreadPool: Create a thread pool of fixed size, if the pool is exhausted, tasks must wait (queued) till a thread becomes free. e.g
ExecutorService service=Executors.newFixedThreadPool(noOfThreads);

2).  CachedThreadPool: Creates a thread pool of unlimited size, but if the threads get freed up, they are reused. Here we do not have the queue, which holds no. of tasks that we have submitted, instead the queue replaced with Synchronous queue, that's why every time you submit a task, it will check if any of the thread is available (free) or not, if no such thread is available it will create a thread, add it in pool and ask the thread to execute the task. If any of the threads is idle for 60 seconds (has no task to execute), then that thread will be killed by the thread pool. e.g
ExecutorService service=Executors.newCachedThreadPool();

3). ScheduledThreadPool: This is specifically for the task, which you want to execute after a certain delay.
  • Service.schedule: You want to perform login checks, security checks after every 10 seconds, you can use Service.schedule to give it a delay of 10 seconds. In this case, the delay queue will be used.
  • Service.scheduleAtFixedRate: Use this when you want to perform recurring checks, say after every 10 seconds. It will store all the tasks you have submitted in the queue, but does not execute, then sequentially, instead the submitted tasks will be executed according to the fixed delay (which is provided). If you have added 8 tasks each with a delay of 10 Minutes and then you add a new task with a delay of 10 seconds. The task with 10 second delay will come in front.
  • Service.scheduleAtFixedDelay: If there is a scenario, where you want to run a task 'x' seconds after the previous instance has run use scheduleAtFixedDelay. This will complete the task, wait for a specified time and then execute the next task. e.g:

ScheduledExecutorService service=Executors.newScheduledThreadPool(coreCount);
service.scheduleAtFixedRate(new CpuIntensiveTask(), 10, 15, TimeUnit.SECONDS);
where: 10 is the time to delay first execution and 15 is the the period between successive executions

4). SingleThreadedExecutor: Creates only a single thread, tasks are executed sequentially form the queue (blocking). If the thread is killed because of some exception, the ThreadPool will recreate the thread.

What are constructor parameters and the LifeCycle methods of ExecutorService in Java?
When you instantiate your Executor Service, a few parameters are initialized. Depending on how you instantiated your Executor Service, you may manually specify these parameters or they may be provided for you by default. These parameters are:
  • corePool size is the minimum number of threads that should be kept in the pool. The number of threads may grow to reach the max pool size (if it is higher than the core pool size), but in general, it represents the number of threads you expect to have alive in the pool. When a task is submitted to the executor, it checks if the actual running number of threads is less than the core pool size. If it is, then it creates a new worker using the specified threadFactory.
  • maxPool size is the maximum number of workers that can be in the pool. If the max pool size is greater than the core pool size, it means that the pool can grow in size, i.e. more workers can be added to the pool. Workers are added to the pool when a task is submitted but the work queue is full. Every time this happens, a new worker is added until the max pool size is reached. If the max pool size has already been reached and the work queue is full, then the next task will be rejected.
  • workQueue is used to queue up tasks for the available worker threads. The queue can be bounded or unbounded. For bounded queues, setting the queue size is an important exercise, as it affects how the worker pool grows and when you start running into RejectedExecutionExceptions. If you have a work pool that you expect to grow; say from a core pool size of 20 workers to a max of 100 workers, then you may not want to set the queue size to a number that is too high, like 10,000, because it means that 10,000 tasks must be enqueued before each additional worker gets added to the pool. Unbounded queues and bounded queues with very high capacities are more suited to be used with fixed size pools (i.e. pools where the core and max pools sizes are the same).
  • keepAliveTime: If the current number of worker threads exceeds the core pool size and a keepAliveTime is set, then worker threads are shut down when there is no more work to do until the number of worker threads is back to the core pool size; a thread will wait for work for the keepAlive time, and when that is exceeded and no work arrives, it will shut down.
  • threadFactory: The factory used to create new threads.
  • rejectedExecutionHandler: Callback to use when tasks submitted are rejected.

Parameter
FixedThreadPool
CachedThreadPool
ScheduledThreadPool
SingleThreaded
corePoolSize
constructor-arg
0
constructor-arg
1
maxPoolSize
same as corePoolSize
Integer.MAX_VALUE
Integer.MAX_VALUE
1
keepAliveTime
0 sec
60 sec
60 sec
0 sec


Pool
Queue Type
Reason?
FixedThreadPool
LinkedBlockingQueue
ArrayBlocking Queue is fixed in size, that's why its not used. Threads are limited, (but tasks are not limited) thus unbounded queue is used to store all tasks
SingleThreadExecutor
LinkedBlockingQueue
CachedThreadPool
SynchronousQueue
Threads are unbounded, thus no need to store the tasks. Synchronous queue is a queue with a single slot, thus any time a task is submitted there will be only one slot, thread pool will empty that slot and use it.
ScheduledThreadPool
DelayedWorkQueue
Special queue that deals with time delays/ schedules.
Custom
ArrayBlockingQueue
Bounded queue to store the tasks, If the queue gets full, new thread is created (as long as count is less than maxPoolSize).

You can set allowCoreThreadTimeOut to true on your ThreadPoolExecutor instance, and if you do so, then not only do workers threads that exceed the core pool size get shut down on idle, but core worker threads also get shut down on idle. By default, this is set to false. i.e the core pool threads are never killed unless allowCoreThreadTimeOut is set to true. By default it's set to false.

What is the role of Executors.unconfigurableExecutorService in Executor Framework?
The unconfigurableExecutorService method in java executor returns an object that delegates all methods of ExecutorService to the given executor so that any other method cannot accessed by cast.

What is the role of ExecutorService in Java?
The java.util.concurrent.ExecutorService interface represents an asynchronous execution mechanism which is capable of executing tasks in the background. An ExecutorService is thus very similar to a thread pool. In fact, the implementation of ExecutorService present in the java.util.concurrent package is a thread pool implementation. e.g:

ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() {
    public void run() {
        System.out.println("Asynchronous task");
    }
});
executorService.shutdown();


First an ExecutorService is created using the newFixedThreadPool() factory method. This creates a thread pool with 10 threads executing tasks.

Second, an anonymous implementation of the Runnable interface is passed to the execute() method. This causes the Runnable to be executed by one of the threads in the ExecutorService

Example of Java Thread Pool

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

final class Task implements Runnable
{
private int taskId;

public Task(int taskId)
{
this.taskId=taskId;
}

@Override
public void run() {
System.out.println("Running a thread with name :"+Thread.currentThread().getName()+", for task id:"+this.taskId);
}
}

public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService exeService=Executors.newFixedThreadPool(5);

for (int i=0; i<20 i="">
{
exeService.submit(new Task(i));
}
}
}

Output:
Running a thread with name :pool-1-thread-2, for task id:1
Running a thread with name :pool-1-thread-5, for task id:4
Running a thread with name :pool-1-thread-2, for task id:5
Running a thread with name :pool-1-thread-2, for task id:7
Running a thread with name :pool-1-thread-4, for task id:3
Running a thread with name :pool-1-thread-1, for task id:0
Running a thread with name :pool-1-thread-3, for task id:2
Running a thread with name :pool-1-thread-1, for task id:10
Running a thread with name :pool-1-thread-4, for task id:9
Running a thread with name :pool-1-thread-2, for task id:8
Running a thread with name :pool-1-thread-5, for task id:6
Running a thread with name :pool-1-thread-2, for task id:14
Running a thread with name :pool-1-thread-2, for task id:16
Running a thread with name :pool-1-thread-4, for task id:13
Running a thread with name :pool-1-thread-1, for task id:12
Running a thread with name :pool-1-thread-3, for task id:11
Running a thread with name :pool-1-thread-1, for task id:19
Running a thread with name :pool-1-thread-4, for task id:18
Running a thread with name :pool-1-thread-2, for task id:17
Running a thread with name :pool-1-thread-5, for task id:15

What is the role of FutureTask and Future in java?
FutureTask is base concrete implementation of Future interface and provides asynchronous processing. It contains the methods to start and cancel a task and also methods that can return the state of the FutureTask as whether it’s completed or cancelled.

We need a callable object to create a future task and then we can use Java Thread Pool Executor to process these asynchronously.

A FutureTask can be used to wrap a Callable or Runnable object. Because FutureTask implements Runnable, a FutureTask can be submitted to an Executor for execution.

How to use Callable and Future in Java?
The run() method of Runnable interface does not return any value, so if you need to get a value back from the now-completed task, you must use a method outside the interface and wait for some kind of notification message that the task completed. e.g:

Runnable runnable = ...;
Thread t = new Thread(runnable);
t.start();
t.join();
String outValue = callMethodToGetTheValue();

With Callable interface (which was introduced in J2SE 5.0) we can get the value by calling call() method. The call() can return an Object or, more specifically, any type that is introduced in the generalized form.

public interface Callable< V  >   {
     V call() throws Exception;
}


We cannot pass a Callable into a Thread to execute, instead ExecutorService is used to execute the Callable object. The service accepts Callable objects to run by way of the submit() method:

< T  >   Future< T  >   submit(Callable< T  >   task)

As the method definition shows, submitting a Callable object to the ExecutorService returns a Future object. The get() method of Future will then block until the task is completed. This is the equivalent of the join() call. Actually, it is the equivalent of both the join() call and the get value call as get() returns the value calculated by the Callable instance.

import java.util.*;
import java.util.concurrent.*;
public class CallableTest {

public static class WordLengthCallable implements Callable {
    private String word;
    public WordLengthCallable(String word) {
      this.word = word;
    }
    public Integer call() {
      return Integer.valueOf(word.length());
    }
}

public static void main(String args[]) throws Exception {
    String[] strArray = new String[2];
    strArray[0] = "Mariam";
    strArray[1] = "Donald";

    ExecutorService pool = Executors.newFixedThreadPool(3); // Executors.newSingleThreadExecutor();
    Set< Future< Integer  >    >   set = new HashSet< Future< Integer  >    >  ();
    for (String word: strArray) {
      Callable< Integer  >   callable = new WordLengthCallable(word);
      Future< Integer  >   future = pool.submit(callable);
      set.add(future);
    }
    int sum = 0;
    for (Future< Integer  >   future : set) {
      sum += future.get();
    }
    System.out.print("The sum of lengths is :"+ sum);
  }
}

ALSO CHECKAll About Java Threads

-K Himaanshu Shuklaa..

No comments:

Post a Comment

RSSChomp Blog Directory