




















































(For more resources related to this topic, see here.)
In a high-performance environment, every costly resource instantiation needs to be minimized. This can be done effectively using pools. The different subsystems in WildFly often use various pools of resources to minimize the cost of creating new ones. These resources are often threads or various connection objects. Another benefit is that the pools work as a gatekeeper, hindering the underlying system from being overloaded. This is performed by preventing client calls from reaching their target if a limit has been reached.
In the upcoming sections of this article, we will provide an overview of the different subsystems and their pools.
The thread pool executor subsystem was introduced in JBoss AS 7. Other subsystems can reference thread pools configured in this one. This makes it possible to normalize and manage the thread pools via native WildFly management mechanisms, and it allows you to share thread pools across subsystems.
The following code is an example taken from the WildFly Administration Guide (https://docs.jboss.org/author/display/WFLY8/Admin+Guide) that describes how the Infinispan subsystem may use the subsystem, setting up four different pools:
<subsystem > <thread-factory name="infinispan-factory" priority="1"/> <bounded-queue-thread-pool name="infinispan-transport"> <core-threads count="1"/> <queue-length count="100000"/> <max-threads count="25"/> <thread-factory name="infinispan-factory"/> </bounded-queue-thread-pool> <bounded-queue-thread-pool name="infinispan-listener"> <core-threads count="1"/> <queue-length count="100000"/> <max-threads count="1"/> <thread-factory name="infinispan-factory"/> </bounded-queue-thread-pool> <scheduled-thread-pool name="infinispan-eviction"> <max-threads count="1"/> <thread-factory name="infinispan-factory"/> </scheduled-thread-pool> <scheduled-thread-pool name="infinispan-repl-queue"> <max-threads count="1"/> <thread-factory name="infinispan-factory"/> </scheduled-thread-pool> </subsystem> ... <cache-container name="web" default-cache="repl"listener-executor=
"infinispan-listener" eviction-executor=
"infinispan-eviction"replication-queue-executor
="infinispan-repl-queue"> <transport executor="infinispan-transport"/> <replicated-cache name="repl" mode="ASYNC" batching="true"> <locking isolation="REPEATABLE_READ"/> <file-store/> </replicated-cache> </cache-container>
The following thread pools are available:
The details of these thread pools are described in the following sections:
The unbounded-queue-thread-pool thread pool executor has the maximum size and an unlimited queue. If the number of running threads is less than the maximum size when a task is submitted, a new thread will be created. Otherwise, the task is placed in a queue. This queue is allowed to grow infinitely.
The configuration properties are shown in the following table:
max-threads
|
Max allowed threads running simultaneously
|
keepalive-time
|
This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) |
thread-factory
|
This specifies the thread factory to use to create worker threads. |
The bounded-queue-thread-pool thread pool executor has a core, maximum size, and a specified queue length. If the number of running threads is less than the core size when a task is submitted, a new thread will be created; otherwise, it will be put in the queue. If the queue's maximum size has been reached and the maximum number of threads hasn't been reached, a new thread is also created. If max-threads is hit, the call will be sent to the handoff-executor. If no handoff-executor is configured, the call will be discarded.
The configuration properties are shown in the following table:
core-threads
|
Optional and should be less that max-threads
|
queue-length
|
This specifies the maximum size of the queue. |
max-threads
|
This specifies the maximum number of threads that are allowed to run simultaneously. |
keepalive-time
|
This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) |
Handoff-executor
|
This specifies an executor to which tasks will be delegated, in the event that a task cannot be accepted. |
allow-core-timeout
|
This specifies whether core threads may time-out; if false, only threads above the core size will time-out. |
thread-factory
|
This specifies the thread factory to use to create worker threads. |
The blocking-bounded-queue-thread-pool thread pool executor has a core, a maximum size and a specified queue length. If the number of running threads is less than the core size when a task is submitted, a new thread will be created. Otherwise, it will be put in the queue. If the queue's maximum size has been reached, a new thread is created; if not, max-threads is exceeded. If so, the call is blocked.
The configuration properties are shown in the following table:
core-threads
|
Optional and should be less that max-threads
|
queue-length
|
This specifies the maximum size of the queue. |
max-threads
|
This specifies the maximum number of simultaneous threads allowed to run. |
keepalive-time
|
This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) |
allow-core-timeout
|
This specifies whether core threads may time-out; if false, only threads above the core size will time-out. |
thread-factory
|
This specifies the thread factory to use to create worker threads |
The queueless-thread-pool thread pool is a thread pool executor without any queue. If the number of running threads is less than max-threads when a task is submitted, a new thread will be created; otherwise, the handoff-executor will be called. If no handoff-executor is configured the call will be discarded.
The configuration properties are shown in the following table:
max-threads
|
Max allowed threads running simultaneously
|
keepalive-time
|
The amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) |
handoff-executor
|
Specifies an executor to delegate tasks to in the event that a task cannot be accepted |
thread-factory
|
The thread factory to use to create worker threads |
The blocking-queueless-thread-pool thread pool executor has no queue. If the number of running threads is less than max-threads when a task is submitted, a new thread will be created. Otherwise, the caller will be blocked.
The configuration properties are shown in the following table:
max-threads
|
Max allowed threads running simultaneously
|
keepalive-time
|
This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) |
thread-factory
|
This specifies the thread factory to use to create worker threads |
The scheduled-thread-pool thread pool is used by tasks that are scheduled to trigger at a certain time.
The configuration properties are shown in the following table:
max-threads
|
Max allowed threads running simultaneously
|
keepalive-time
|
This specifies the amount of time that pool threads should be kept running when idle. (If not specified, threads will run until the executor is shut down.) |
thread-factory
|
This specifies the thread factory to use to create worker threads |
All of the pools just mentioned can be administered and monitored using both CLI and JMX (actually, the Admin Console can be used to administer, but not see, any live data). The following example and screenshots show the access to an unbounded-queue-thread-pool called test.
Using CLI, run the following command:
/subsystem=threads/unbounded-queue-thread-pool=test:read-resource
(include-runtime=true)
The response to the preceding command is as follows:
{ "outcome" => "success", "result" => { "active-count" => 0, "completed-task-count" => 0L, "current-thread-count" => 0, "keepalive-time" => undefined, "largest-thread-count" => 0, "max-threads" => 100, "name" => "test", "queue-size" => 0, "rejected-count" => 0, "task-count" => 0L, "thread-factory" => undefined } }
Using JMX (query and result in the JConsole UI), run the following code:
jboss.as:subsystem=threads,unbounded-queue-thread-pool=test
An example thread pool by JMX is shown in the following screenshot:
An example thread pool by JMX
The following screenshot shows the corresponding information in the Admin Console
Example thread pool—Admin Console
According to the official JIRA case WFLY-462 (https://issues.jboss.org/browse/WFLY-462), the central thread pool configuration has been targeted for removal in future versions of the application server. It is, however, uncertain that all subprojects will adhere to this. The actual configuration will then be moved out to the subsystem itself. This seems to be the way the general architecture of WildFly is moving in terms of pools—moving away from generic ones and making them subsystem-specific. The different types of pools described here are still valid though.
Note that, contrary to previous releases, Stateless EJB is no longer pooled by default. More information of this is available in the JIRA case WFLY-1383. It can be found at https://issues.jboss.org/browse/WFLY-1383.