Chapter 24. Thread Management Each JBoss EAP messaging server maintains a single thread pool for general use, and scheduled thread pool for scheduled use. A Java scheduled thread pool cannot be configured to use a standard thread pool, otherwise we could use a single thread pool for both scheduled and non scheduled activity. Note that JBoss EAP uses the new, non-blocking NIO. By default, JBoss EAP messaging uses a number of threads equal to three times the number of cores, or hyper-threads, as reported by .getRuntime().availableProcessors() for processing incoming packets. To override this value, set the number of threads by specifying the nio-remoting-threads parameter in the transport configuration. See Configuring the Messaging Transports for more information. 24.1. Server Scheduled Thread Pool The server scheduled thread pool is used for most activities on the server side that require running periodically or with delays. It maps internally to a java.util.concurrent.ScheduledThreadPoolExecutor instance. The maximum number of thread used by this pool is configured using the scheduled-thread-pool-max-size parameter. The default value is 5 threads. A small number of threads is usually sufficient for this pool. To change this value for the default JBoss EAP messaging server, use the following management CLI command: 24.2. Server General Purpose Thread Pool The general purpose thread pool is used for most asynchronous actions on the server side. It maps internally to a java.util.concurrent.ThreadPoolExecutor instance. The maximum number of threads used by this pool is configured using the thread-pool-max-size attribute. If thread-pool-max-size is set to -1 , the thread pool has no upper bound and new threads are created on demand if there are not enough threads available to fulfill a request. If activity later subsides, then threads are timed out and closed. If thread-pool-max-size is set to a positive integer greater than zero, the thread pool is bounded. If requests come in and there are no free threads available in the pool, requests will block until a thread becomes available. It is recommended that a bounded thread pool be used with caution since it can lead to deadlock situations if the upper bound is configured too low. The default value for thread-pool-max-size is 30 . To set a new value for the default JBoss EAP messaging server, use the following management CLI command. See the ThreadPoolExecutor Javadoc for more information on unbounded (cached), and bounded (fixed) thread pools. 24.3. Monitoring Server Thread Utilization Check thread utilization to ensure you have configured the size of the thread pools appropriately. To check thread utilization, issue the following CLI command: The system returns results similar to the following { "outcome" => "success", "result" => { "global-client-scheduled-thread-pool-active-count" => 0, "global-client-scheduled-thread-pool-completed-task-count" => 0L, "global-client-scheduled-thread-pool-current-thread-count" => 0, "global-client-scheduled-thread-pool-keepalive-time" => 10000000L, "global-client-scheduled-thread-pool-largest-thread-count" => 0, "global-client-scheduled-thread-pool-max-size" => undefined, "global-client-scheduled-thread-pool-task-count" => 0L, "global-client-thread-pool-active-count" => 0, "global-client-thread-pool-completed-task-count" => 2L, "global-client-thread-pool-current-thread-count" => 2, "global-client-thread-pool-keepalive-time" => 60000000000L, "global-client-thread-pool-largest-thread-count" => 2, "global-client-thread-pool-max-size" => undefined, "global-client-thread-pool-task-count" => 2L, "connection-factory" => undefined, "connector" => undefined, "discovery-group" => undefined, "external-jms-queue" => undefined, "external-jms-topic" => undefined, "http-connector" => undefined, "in-vm-connector" => undefined, "jms-bridge" => undefined, "pooled-connection-factory" => undefined, "remote-connector" => undefined, "server" => {"default" => undefined} } } Table 24.1. Thread Utilization Data Utilization attribute Description global-client-scheduled-thread-pool-active-count The number of scheduled pool threads in use by all ActiveMQ clients currently executing tasks. global-client-scheduled-thread-pool-completed-task-count The number of tasks using scheduled pool threads that have been executed by all ActiveMQ clients since the server was booted. global-client-scheduled-thread-pool-current-thread-count The current number of threads in the scheduled pool that are in use by all Active MQ clients. global-client-scheduled-thread-pool-keepalive-time The amount of time to keep threads in the scheduled thread pool running when idle. global-client-scheduled-thread-pool-largest-thread-count The largest number of threads in the scheduled pool that have ever been used simultaneously by all Active MQ clients. global-client-scheduled-thread-pool-max-size Maximum number of threads in the the scheduled pool used by all ActiveMQ clients running inside this server. global-client-scheduled-thread-pool-task-count The total number of tasks in the scheduled thread pool that have ever been scheduled by all Active MQ clients. global-client-thread-pool-active-count The number of general-purpose pool threads being used by all ActiveMQ clients currently executing tasks. global-client-thread-pool-completed-task-count The number of tasks using general-purpose pool threads that have been executed by all ActiveMQ clients. global-client-thread-pool-current-thread-count The current number of threads in the general-purpose pool that are in use by all Active MQ clients. global-client-thread-pool-keepalive-time The amount of time that threads in the general-purpose thread pool should be kept running when idle. global-client-thread-pool-largest-thread-count The largest number of threads in the general-purpose pool that have ever been used simultaneously by all Active MQ clients. global-client-thread-pool-max-size Maximum number of threads in the general-purpose pool used by all ActiveMQ clients running inside this server. global-client-thread-pool-task-count The total number of tasks in the general-purpose thread pool that have ever been scheduled by all Active MQ clients. 24.4. Expiry Reaper Thread A single thread is also used on the server side to scan for expired messages in queues. We cannot use either of the thread pools for this since this thread needs to run at its own configurable priority. 24.5. Asynchronous IO Asynchronous IO has a thread pool for receiving and dispatching events out of the native layer. It is on a thread dump with the prefix ArtemisMQ-AIO-poller-pool . JBoss EAP messaging uses one thread per opened file on the journal (there is usually one). There is also a single thread used to invoke writes on libaio. It is done to avoid context switching on libaio that would cause performance issues. This thread is found on a thread dump with the prefix ArtemisMQ-AIO-writer-pool . 24.6. Client Thread Management JBoss EAP includes a client thread pool used for creating client connections. This pool is separate from the static pools mentioned earlier in this chapter and is used by JBoss EAP when it behaves like a client. For example, client thread pool clients are created as cluster connections with other nodes in the same cluster, or when the Artemis resource adapter connects to a remote Apache ActiveMQ Artemis messaging server integrated in a remote instance of JBoss EAP. There is a pool for scheduled client threads as well. Note With the release of JBoss EAP 7.1, client threads now timeout after 60 seconds of no activity. Setting Client Thread Pool Size Using the Management CLI Use the management CLI to configure the size of both the client thread pool and the client scheduled thread pool. Pool sizes set using the management CLI will have precedence over the sizings set using system properties. The command below sets the client thread pool. There is no default value defined for this attribute. If the attribute is not defined, the maximum size of the pool is determined to be eight (8) times the number of CPU core processors. To review the current settings, use the following command. The client scheduled thread pool size is set using the following command. The following will display the current pool size for the client scheduled thread pool. The default value is 5 . Setting Client Thread Pool Size Using System Properties The following system properties can be used to set the size of the client's global and global scheduled thread pools respectively: activemq.artemis.client.global.thread.pool.max.size activemq.artemis.client.global.scheduled.thread.pool.core.size The system properties can then be referenced in XML configuration, as in the example below. Note Pool sizes set using the management CLI will have precedence over sizes set by system properties. <subsystem xmlns="urn:jboss:domain:messaging-activemq:4.0"> <global-client thread-pool-max-size="USD{activemq.artemis.client.global.thread.pool.max.size}" scheduled-thread-pool-max-size="USD{activemq.artemis.client.global.scheduled.thread.pool.core.size}" /> <server ...> </server> ... </subsystem> Configuring a Client to Use Its Own Thread Pool A client can configure each of its ClientSessionFactory instances to not use the pool provided by JBoss EAP, but instead to use its own client thread pool. Any sessions created from that ClientSessionFactory will use the newly created pool. To configure a ClientSessionFactory instance to use its own pools, invoke the appropriate setter methods immediately after you created the factory. For example: ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(transportConfiguration); locator.setUseGlobalPools(true); locator.setThreadPoolMaxSize(-1); locator.setScheduledThreadPoolMaxSize(10); ClientSessionFactory myFactory = locator.createSessionFactory(); If you are using the Jakarta Messaging API, you can set the same parameters on the ClientSessionFactory . For example: ActiveMQConnectionFactory myConnectionFactory = ActiveMQJMSClient.createConnectionFactory(url, "ConnectionFactoryName"); myConnectionFactory.setUseGlobalPools(false); myConnectionFactory.setScheduledThreadPoolMaxSize(10); myConnectionFactory.setThreadPoolMaxSize(-1); If you are using JNDI to instantiate ActiveMQConnectionFactory instances, you can also set these parameters using the management CLI, as in the examples given below for a standalone instance of JBoss EAP. Note that the management CLI will remind you that a reload of the instance is required after you execute each of the above commands.

Commands:
/subsystem=messaging-activemq/server=default:write-attribute(name=scheduled-thread-pool-max-size,value=10)
/subsystem=messaging-activemq/server=default:write-attribute(name=thread-pool-max-size,value=40)
/subsystem=messaging-activemq:read-resource(include-runtime)
{ "outcome" => "success", "result" => { "global-client-scheduled-thread-pool-active-count" => 0, "global-client-scheduled-thread-pool-completed-task-count" => 0L, "global-client-scheduled-thread-pool-current-thread-count" => 0, "global-client-scheduled-thread-pool-keepalive-time" => 10000000L, "global-client-scheduled-thread-pool-largest-thread-count" => 0, "global-client-scheduled-thread-pool-max-size" => undefined, "global-client-scheduled-thread-pool-task-count" => 0L, "global-client-thread-pool-active-count" => 0, "global-client-thread-pool-completed-task-count" => 2L, "global-client-thread-pool-current-thread-count" => 2, "global-client-thread-pool-keepalive-time" => 60000000000L, "global-client-thread-pool-largest-thread-count" => 2, "global-client-thread-pool-max-size" => undefined, "global-client-thread-pool-task-count" => 2L, "connection-factory" => undefined, "connector" => undefined, "discovery-group" => undefined, "external-jms-queue" => undefined, "external-jms-topic" => undefined, "http-connector" => undefined, "in-vm-connector" => undefined, "jms-bridge" => undefined, "pooled-connection-factory" => undefined, "remote-connector" => undefined, "server" => {"default" => undefined} } }
/subsystem=messaging-activemq:write-attribute(name=global-client-thread-pool-max-size,value= POOL_SIZE )
/subsystem=messaging-activemq:read-attribute(name=global-client-thread-pool-max-size)
/subsystem=messaging-activemq:write-attribute(name=global-client-scheduled-thread-pool-max-size,value= POOL_SIZE )
/subsystem=messaging-activemq:read-attribute(name=global-client-scheduled-thread-pool-max-size)
<subsystem xmlns="urn:jboss:domain:messaging-activemq:4.0"> <global-client thread-pool-max-size="USD{activemq.artemis.client.global.thread.pool.max.size}" scheduled-thread-pool-max-size="USD{activemq.artemis.client.global.scheduled.thread.pool.core.size}" /> <server ...> </server> </subsystem>
ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(transportConfiguration); locator.setUseGlobalPools(true); locator.setThreadPoolMaxSize(-1); locator.setScheduledThreadPoolMaxSize(10); ClientSessionFactory myFactory = locator.createSessionFactory();
ActiveMQConnectionFactory myConnectionFactory = ActiveMQJMSClient.createConnectionFactory(url, "ConnectionFactoryName"); myConnectionFactory.setUseGlobalPools(false); myConnectionFactory.setScheduledThreadPoolMaxSize(10); myConnectionFactory.setThreadPoolMaxSize(-1);
/subsystem=messaging-activemq/server=default/connection-factory=myConnectionFactory:write-attribute(name=use-global-pools,value=false) /subsystem=messaging-activemq/server=default/connection-factory=myConnectionFactory:write-attribute(name=scheduled-thread-pool-max-size,value=10) /subsystem=messaging-activemq/server=default/connection-factory=myConnectionFactory:write-attribute(name=thread-pool-max-size,value=1)