Tuesday, March 27, 2012

Thread Pooling in Java - Part 2 - Internals.

For the basics of Java threads, please check this post, http://karthikpresumes.blogspot.in/2013/02/java-multi-threading-basics.html

In the first part, we had analyzed the needs for Fixed and cached Thread Pools.

http://karthikpresumes.blogspot.in/2012/03/thread-pooling-in-java-intuitive.html


Fixed thread pools have fixed number of running threads operating on a finite unbounded tasks queue.
Cached thread pools spawn as many number of threads as the task count at any time and have a Synchronized Queue.

And we had seen use cases for each of the thread pools in the previous part. Now, what if an use case needs the mixed behaviors of the above. For instance, behave like a CachedThreadPool until a fixed number of tasks.

Analysis of the implementations of the above thread pools would open new doors for solving interesting variants of thread-pool based problems.

Actually, both Fixed and Cached thread pools creation, internally would create instance of ThreadPoolExecutor with different parameters.
For instance, let us analyze the FixedThreadPool call,

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}

The declaration of ThreadPoolExecutor is,

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) { ...

Let us try to understand each and every parameter.

CorePoolSize: This represents the number of threads to be alive even in the absence of any task. In Fixed Thread Pool, it should be equal to the total or Max thread count as we know the optimal number of threads and destroying/ recreating the threads incur performance hurt.

Maximum Pool Size: This represents the maximum number of threads that could be created in the thread pool. If the count of running threads exceeds "corePoolSize" and queue of waiting tasks are filled completely, then a new thread could be created if Maximum Pool Size > Core Pool Size.

Keep Alive Time: In case threads created exceeds the corePoolSize and some of the threads are idle for "keepAliveTime" then those would be killed to save the resources in the System. And the next parameter is the unit for KeepAliveTime.

BlockingQueue: It describes the queue to be used for Waiting tasks. For Fixed Thread Pool, it is unbounded. And for CachedThreadPool, it is SynchronizedQueue, means at any time, queued task must be immediately served; means no task could be queued for processing later.

So, if we could statistically analyze the peak and average traffic of incoming tasks, we could come up with optimal values for Core, Max pool size and KeepAliveTime; which could make our thread-pool efficient and resources conservative. :)

To make the discussion complete, we will try to understand the implementation of ThreadPoolExecutor.

Well, we need to discuss what happens when Execute of ThreadPoolExecutor called.

Algorithm which backs Execute is simple. If number of threads is less than the core pool size, a new thread will be spawned to handle this new task. If the number of active threads exceeds the core pool size and queue is filled up fully, algorithm would check for the spawning of additional threads, constrained by the max pool size count, is possible; If not, rejection handler would be called.

ThreadPoolExecutor holds a control state variable ctl, which is an AtomicInteger, provides some useful information like effective worker threads and state of ThreadPool(Running, Shutting down, etc). And there are several utility functions around this variable.

Apart from this, there are several other functionalities which assist the main functionalities like termination of Thread Pool and thread factory, etc. People interested in that, could dive into the source code for complete understanding. I hope I tried my best to keep the information concise.

Thanks for Reading.

5 comments:

  1. Hi! Karthik
    I have a question what does keepAliveTime = 0L indicates?
    Does it mean it will keep the thread in the queue till it shutdowns if not what shuold be the value of keepAliveTime to keep the task in the queue for threadExecutor lifetime ?

    ReplyDelete
  2. In Fixed thread pool, this value doesn't matter as no extra threads would be created than the core pool size as the tasks queue is unbounded. Generally, it means if there are threads more than core pool size and idle for keep-alive time, those may be destroyed to make resources free.

    ReplyDelete
  3. I found my answer "keepAliveTime should be LONG.MAX_VALUE to keep the task in the queue for threadExecutor lifetime"

    ReplyDelete
  4. Good job, I wish I would have found your blog when I was actually doing some java programming, I enjoy your explanations, very straight forward. -D, texas, usa

    ReplyDelete
  5. public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue());
    }
    Here the min number of thread and Max number of thread is equal and liftime for the thread is infinite

    public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
    60L, TimeUnit.SECONDS,
    new SynchronousQueue());
    }
    in cached pool model min number of thread is 0 and Max in integer max value , in the time given for thread is 60 sec , if the thread is not used for 60 or more second thread will be destroyed .


    @ Karthik my question , how threadpool internally manage thread object to execute task .....internal working of ThreadPool

    ReplyDelete