Chapter 40. Thread management

This chapter describes how HornetQ uses and pools threads and how to manage them.
First we will discuss how threads are managed and used on the server side, then we will look at the client side.

40.1. Server-Side Thread Management

Each HornetQ Server maintains a single thread pool for general use, and a 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.
When using old (blocking) IO, a separate thread pool is also used to service connections. Since old IO requires a thread per connection, it does not make sense to get them from the standard pool as the pool will easily get exhausted if too many connections are made, resulting in the server "hanging" since it has no remaining threads to do anything else. If you require the server to handle many concurrent connections, make sure to use NIO, not old IO.
When using new IO (NIO), HornetQ will, by default, use a number of threads equal to three times the number of cores (or hyper-threads) as reported by Runtime.getRuntime().availableProcessors() for processing incoming packets. To override this value, set the number of threads by specifying the parameter nio-remoting-threads in the transport configuration. Refer to Chapter 14, Configuring the Transport for more information on this.
There are also a small number of other places where threads are used directly:

40.1.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 threads used by this pool is configured in <JBOSS_HOME>/jboss-as/server/<PROFILE>/deploy/hornetq/hornetq-configuration.xml with the scheduled-thread-pool-max-size parameter. The default value is 5 threads. A small number of threads is usually sufficient for this pool.

40.1.2. General Purpose Server Thread Pool

This 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 in <JBOSS_HOME>/jboss-as/server/<PROFILE>/deploy/hornetq/hornetq-configuration.xml with the thread-pool-max-size parameter.
If a value of -1 is specified, the thread pool has no upper bound and new threads will be created on demand if there are not enough threads available to satisfy a request. If activity later subsides then threads are timed-out and closed.
If a value of n where n is a positive integer greater than zero is used this signifies that the thread pool is bounded. If more requests come in and there are no free threads in the pool and the pool is full then requests will block until a thread becomes available. It is recommended that a bounded thread pool is used with caution since it can lead to dead-lock situations if the upper bound is chosen to be too low.
The default value for thread-pool-max-size is 30.
See the J2SE Javadoc for more information on unbounded (cached), and bounded (fixed) thread pools.

40.1.3. 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.
For more information on configuring the reaper, refer to Chapter 20, Message Expiry.

40.1.4. Asynchronous IO

Asynchronous IO has a thread pool for receiving and dispatching events out of the native layer. You will find it on a thread dump with the prefix HornetQ-AIO-poller-pool. HornetQ 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, which avoids performance issues with context switching. You will find this thread on a thread dump with the prefix HornetQ-AIO-writer-pool.