WLS work manager configuration supports three different types of constraints - minimum threads, maximum threads, and capacity constraints. Here we are going to focus on some issues related to using the minimum and maximum threads constraints.
First a brief introduction on the self-tuning thread pool in WLS. Each WLS server instance maintains a single thread pool to be shared by all work managers defined on that WLS instance. This is different from the OC4J thread pool model in which separate thread pools are created for each configured thread pool. The self-tuning thread pool would also adjust its pool size automatically based on the throughput history that WLS gathers every 2 seconds. Thus there is no need to preset the minimum and maximum number of threads in the self-tuning thread pool.
Minimum Threads Constraint
According to the WLS documentation, the minimum threads constraint "guarantees the number of threads the server will allocate to affected requests to avoid deadlocks." It makes sure that during periods of high workloads, there would still be a certain number of threads from the self-tuning thread pool available to process work requests for all work managers that reference the minimum threads constraint.
Suppose we have a work manager called WM1 with no minimum threads constraint configured, and a new work request is scheduled for WM1 during times of high work load where all the threads in the self-tuning thread pool are already working on servicing other work requests. The new work request will be added to a queue waiting for some threads in the thread pool to be freed up before it can be processed.
Suppose WM1 is modified to reference a minimum threads constraint C1 with a value of 2, and that it is the only work manager referencing C1. If a work request for WM1 is scheduled when there are available threads in the thread pool, WLS will pick an idle thread for processing the work regardless of whether WM1 references any minimum threads constraint. However, if the work is scheduled during times of high work load and that there are no available threads in the self-tuning thread pool, WLS will first check and see how many threads in the thread pool are currently processing work requests for WM1. In this example, if there are fewer than 2 threads, WLS would create a new thread to handle the work request for WM1. However, if there are already 2 threads in the self tuning thread pool that are executing work on behalf of WM1, the new work request would be put into a queue just like in the case when there is no minimum threads constraint being configured.
It should be noted that after the work request is finished, the newly created thread will be returned to the self-tuning thread pool and would be available for processing requests from any work manger. So using the minimum threads constraint could result in increasing the number of threads in the self-tuning thread pool. This may not be desirable as it might result in degraded overall server throughput due to the additional context switching among threads, at least before the self-tuning thread pool adjusts to its optimal pool size again. Another possible side-effect of using the minimum threads constraint is that work requests that would have otherwise be put on a queue would instead be executed in a new thread. This would result in more work requests being processed for such work manager than its configured value in the fair share request class if one is configured. Thus the minimum threads constraint should be used only sparingly.
What the minimum threads constraint will not do for the work manager is that no threads will be created specifically for it in the self tuning thread pool during WLS startup. There will not be any threads set aside in the self-tuning thread pool waiting to handle work requests for WM1. Any idle threads in the self-tuning thread pool would be available to process work requests for any work manager.
Multiple work managers can reference the same minimum threads constraint, but the constraint will be applied to all the work managers that are referencing it. Suppose two work managers WM1 and WM2 both reference the same minimum threads constraint C1 with a configured value of 2. The self-tuning thread pool will create new thread for processing work requests for WM1 or WM2 only when there is no more idle threads in the thread pool and that there are fewer than 2 threads currently processing requests for either work managers. In other words, if there are already 2 threads processing work for WM1, the self-tuning thread pool will not create a new thread for the new incoming request for WM2. To have a minimum of 2 threads for each of the two work managers, each work manager would need to reference a different minimum threads constraint, each configured to have a value of 2.
The minimum threads constraint in WLS work manager is most suitable for making sure threads are available for processing work for a work manager during a period of high work load. Users should consider adding a minimum threads constraint to a work manager configuration when it is critical that progress must be made for an application even when the WLS server is under very heavy load, such as work that would have resulted in server-to-server deadlock if not being processed promptly. It is not to be used as a mean of prioritizing workload among different work managers. Users should be looking into using either the fair share request class or the response time request class for that purpose instead.
Maximum Threads Constraint
The maximum threads constraint "limits the number of concurrent threads executing requests from the constrained work set" according to the WLS documentation. It limits the number of threads in the self-tuning thread pool that can be used at any time for executing work for all work managers that references the same constraint. It is not, however, used for limiting the size of the self-tuning thread pool.
More than one work manager can reference the same maximum threads constraint, and any threads processing requests from any of these work manager would count against the limit configured in the maximum threads constraint. This is useful for limiting thread usages for related work managers.
Suppose a maximum threads constraint C2 is defined with a value of 10 and only one work manager WM3 is defined to use C2 as its maximum threads constraint. When 10 threads from the thread pool are already processing work requests for WM3, any additional work requests for WM3 will be put on a queue for C2 even if there are idle threads available in the self-tuning thread pool. The queued requests will be picked up for processing in the same order as they arrived when work requests for WM3 are completed.
Note that when the maximum threads constraint is reached, WLS may no longer able to honor the ratios as defined in the fair share or response time request classes. This is because fewer work requests will be processed for work managers with maximum threads constraint defined that would be otherwise allowed according to the configured values in the request classes. Suppose work manager WM3 in our previous example is defined with a fair share request class of value 80, while another work manager WM4 is defined with a fair share request class of value 20. During a period of sufficient load, WLS would likely process fewer requests for WM3 and have a thread-usage ratio lower than the configured 80:20 ratio between WM3 and WM4 once the maximum threads constraint for WM3 is reached.
What happens to this ratio if both WM3 and WM4 both reference the same maximum threads constraint C2? Assuming the system is under sufficient load, and that the maximum threads constraint is reached, additional requests from both WM3 and WM4 will be added to the same queue. The requests for both work managers will then be processed in the same order as they arrive and would not be according to the configured request class ratio. Thus the thread-usage ratio will not be maintained in this case either.
Like the minimum threads constraint, the maximum threads constraint is not designed as a mean to prioritize workloads among different work managers. It is most useful when there are other known limitations where a hard upper limit should be put on the number of threads that should be assigned for processing work requests, and that allocating more threads for processing the workload would not increase the overall throughput. One such example would be when the throughput of an application is limited by the size of an underlying resource pool.
It is important to understand how the minimum and maximum threads constrains work in WLS work managers. They are each useful in specific use cases. But for general work load balancing among various work managers, fair share and response time request classes should be used instead. Please refer to the documentation for more information on work managers.