Wednesday, January 16, 2013

Thread Pooling in Java - I

Introduction:

 "Every user wish for user fast and user friendly application"
To fulfill user's wish every programmer tries to write efficient programs. Then tries to optimize and re-optimize the code. But there comes the time when single thread processing can not provide faster results on same hardware configuration. There comes the necessity of multi-threading. So programmer decide to go for it but it comes with some challenges:
  1. How many thread application should be able to create? If it will create too many thread, it might choke other process, if the thread count is too less, it might not provide user the desired experience. So what should be thread count in pool?
  2. When to introduce thread? If we somehow come up with solution to first problem and decide the thread count for application/process then we need to decide when to create these threads. Shell we create all these thread in beginning or we do it on demand? But how to know when demand is high?
  3. When thread should die? If we decide that thread should be created on demand basis, so what happens to the thread when demand decreases? How long should these thread wait in pool and consume system resources?
  4. What happens to the tasks if application is not able to process them at certain point of time? Will these tasks be stored in memory, How many unprocessed task we want to keen in memory?

Solution:

 If you start to think about all these challenges, you will realize that you have to write good amount of code to overcome each one of them. Few years ago there was no choice but to write this type of code, but now Java concurrency package come up with generic solution (ThreadPoolExecutor) to these problems.
ThreadPoolExecutor receives following arguments :
  • corePoolSize: the number of threads to keep in the pool, even if they are idle
  • maximumPoolSize: the maximum number of threads to allow in the pool
  • keepAliveTime: when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
  • unit: the time unit for the keepAliveTime argument
  • workQueue: the queue to use for holding tasks before they are executed. 
Here is one example implementation:

In this example, I informed application to start 2 threads and thread count could be increased to 4. If you submit 4 task at a time application is not going to start 4 threads at a time and finish all tasks at a time but will keep two tasks in queue and whenever any of these thread will be free it will pick up the process from queue. So when would be 4 threads running in parallel? In source code we have defined the size of task queue to 50. Lets consider the case when your queue already has 50 tasks and now you are trying to add another task in queue at this time new process will be created. So reducing the size of queue will result more number of threads in thread pool but it will create a risk of rejection of task if application hits it maximum capacity, so chose it wisely. You can use java profiling to check how many threads are created and when these threads are created.
Here is snapshot of thread profile for execution of the program when workQueue size reduced to 6.

 In this snapshot we can see that the thread-3&4 created when system hit by more requests then workQueue size. This snapshot also show that the thread-3&4 died after waiting 30 ms.


References:
http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html

No comments:

Post a Comment