Class ThreadPoolTaskExecutor

java.lang.Object
org.jtrim2.executor.DelegatedTaskExecutorService
org.jtrim2.executor.ThreadPoolTaskExecutor
All Implemented Interfaces:
Executor, ContextAwareTaskExecutor, ContextAwareTaskExecutorService, MonitorableTaskExecutor, MonitorableTaskExecutorService, TaskExecutor, TaskExecutorService

public final class ThreadPoolTaskExecutor extends DelegatedTaskExecutorService implements MonitorableTaskExecutorService
A TaskExecutorService implementation which executes submitted tasks on a group of threads. This implementation is similar to the java.util.concurrent.ThreadPoolExecutor in Java but implements TaskExecutorService instead of ExecutorService.

Note: Consider using ThreadPoolBuilder instead of directly creating an instance of ThreadPoolTaskExecutor.

Executing new tasks

Tasks can be submitted by one of the submit or execute methods.

When a new task is submitted, ThreadPoolTaskExecutor and there is an idle thread waiting for tasks to be executed, an attempt will be made to execute the submitted task on an idle thread and no new thread will be started. This attempt fails only rarely under extreme contention, in which case a new thread is started even though there was an idle thread.

In case there is no idle thread waiting and a new thread can be started without exceeding the maximum number of allowed threads, a new thread will be started to execute the submitted task.

In case there is no idle thread waiting and there are already as many threads executing tasks as allowed, the submitted task will be added to an internal queue from which the background threads will eventually remove and execute them. Note that the size of the queue can be limited and if this limit is reached, the submitting submit or execute method will block and wait until the task can be added to the queue.

Cancellation of tasks

Canceling a task which was not yet started and is still in the queue will immediately remove it from the queue and no references will be retained to the task (allowing it to be garbage collected if not referenced by external code).

Canceling a task will cause the CancellationToken passed to it, signal cancellation request. In this case the task may decide if it is to be canceled or not. If the task throws an OperationCanceledException, task execution is considered to be canceled. Note that if the task throws an OperationCanceledException it is always assumed to be canceled, even if the CancellationToken does not signal a cancellation request.

Number of referenced tasks

The maximum number of tasks referenced by a ThreadPoolTaskExecutor at any given time is the maximum size of its queue plus the maximum number of allowed threads. The ThreadPoolTaskExecutor will never reference tasks more than this. Note however, that not yet returned execute methods always reference their task specified in their argument (obviously this is unavoidable) and there is no limit on how many times the user can concurrently call these methods.

Terminating ThreadPoolTaskExecutor

The ThreadPoolTaskExecutor must always be shut down when no longer needed, so that it may shutdown its threads. If the user fails to shut down the ThreadPoolTaskExecutor (either by calling shutdown() or shutdownAndCancel()) and the garbage collector notifies the ThreadPoolTaskExecutor that it has become unreachable (through finalizers), it will be logged as an error using the logging facility of Java (in a Level.SEVERE log message).

Comparison with ThreadPoolExecutor

Table for quick feature comparison
Feature ThreadPoolTaskExecutor ThreadPoolExecutor
Immediate cancellation Yes. No, tasks remain in the queue until attempted to be executed.
Cancellation strategy of executing tasks Relies on a CancellationToken. Relies on thread interrupts.
Tracking the state of a submitted task Not directly. Submitted tasks must be wrapped and CompletionStage must be used to listen for completion Possible using the returned Future.
Waiting until the task finished executing Possible using the returned CompletionStage. Not possible, if task was canceled by shutdownNow.
Do cleanup even if task was canceled Yes, using the returned CompletionStage. No, only if the task was refused when submitting.
User defined thread factory Yes Yes
Automatically stop idle threads Yes Yes
Limit the number of threads Yes Yes
New thread start policy Starts a new thread only if there are no idle threads and the maximum number of threads was not reached. Starts a new thread always unless the maximum number of threads was reached.
Increase number of threads over the limit, if queue is full No Yes and configurable
User defined implementation for the internal queue No Yes
Throttle, when the task queue is large Yes Yes, with some limitations
Asynchronous notification of termination Yes Only to subclasses
Shut down and cancel submitted tasks Yes Yes

Thread safety

Methods of this class are safely accessible from multiple threads concurrently.

Synchronization transparency

Method of this class are not synchronization transparent unless otherwise noted.
See Also:
  • Constructor Details

    • ThreadPoolTaskExecutor

      public ThreadPoolTaskExecutor(String poolName)
      Creates a new ThreadPoolTaskExecutor initialized with specified name.

      The default maximum number of threads is Runtime.getRuntime().availableProcessors().

      The default maximum queue size is Integer.MAX_VALUE making it effectively unbounded.

      The default timeout value after idle threads stop is 5 seconds.

      The newly created ThreadPoolTaskExecutor will not have any thread started. Threads will only be started when submitting tasks (as required).

      Note: Consider using ThreadPoolBuilder instead of directly creating an instance of ThreadPoolTaskExecutor.

      Parameters:
      poolName - the name of this ThreadPoolTaskExecutor for logging and debugging purposes. Setting a descriptive name might help when debugging or reading logs. This argument cannot be null.
      Throws:
      IllegalArgumentException - thrown if an illegal value was specified for any of the int arguments
      NullPointerException - thrown if the specified name for this ThreadPoolTaskExecutor is null
    • ThreadPoolTaskExecutor

      public ThreadPoolTaskExecutor(String poolName, int maxThreadCount)
      Creates a new ThreadPoolTaskExecutor initialized with the given properties.

      The default maximum queue size is Integer.MAX_VALUE making it effectively unbounded.

      The default timeout value after idle threads stop is 5 seconds.

      The newly created ThreadPoolTaskExecutor will not have any thread started. Threads will only be started when submitting tasks (as required).

      Note: Consider using ThreadPoolBuilder instead of directly creating an instance of ThreadPoolTaskExecutor.

      Parameters:
      poolName - the name of this ThreadPoolTaskExecutor for logging and debugging purposes. Setting a descriptive name might help when debugging or reading logs. This argument cannot be null.
      maxThreadCount - the maximum number of threads to be executing submitted tasks concurrently. The ThreadPoolTaskExecutor will never execute more tasks concurrently as this number. This argument must be greater than or equal to 1.
      Throws:
      IllegalArgumentException - thrown if an illegal value was specified for any of the int arguments
      NullPointerException - thrown if the specified name for this ThreadPoolTaskExecutor is null
    • ThreadPoolTaskExecutor

      public ThreadPoolTaskExecutor(String poolName, int maxThreadCount, int maxQueueSize)
      Creates a new ThreadPoolTaskExecutor initialized with the given properties.

      The default timeout value after idle threads stop is 5 seconds.

      The newly created ThreadPoolTaskExecutor will not have any thread started. Threads will only be started when submitting tasks (as required).

      Note: Consider using ThreadPoolBuilder instead of directly creating an instance of ThreadPoolTaskExecutor.

      Parameters:
      poolName - the name of this ThreadPoolTaskExecutor for logging and debugging purposes. Setting a descriptive name might help when debugging or reading logs. This argument cannot be null.
      maxThreadCount - the maximum number of threads to be executing submitted tasks concurrently. The ThreadPoolTaskExecutor will never execute more tasks concurrently as this number. This argument must be greater than or equal to 1.
      maxQueueSize - the maximum size of the internal queue to store tasks not yet executed due to all threads being busy executing tasks. This argument must be greater than or equal to 1 and is recommended to be (but not required) greater than or equal to maxThreadCount.
      Throws:
      IllegalArgumentException - thrown if an illegal value was specified for any of the int arguments
      NullPointerException - thrown if the specified name for this ThreadPoolTaskExecutor is null
    • ThreadPoolTaskExecutor

      public ThreadPoolTaskExecutor(String poolName, int maxThreadCount, int maxQueueSize, long idleTimeout, TimeUnit timeUnit)
      Creates a new ThreadPoolTaskExecutor initialized with the given properties.

      The newly created ThreadPoolTaskExecutor will not have any thread started. Threads will only be started when submitting tasks (as required).

      Note: Consider using ThreadPoolBuilder instead of directly creating an instance of ThreadPoolTaskExecutor.

      Parameters:
      poolName - the name of this ThreadPoolTaskExecutor for logging and debugging purposes. Setting a descriptive name might help when debugging or reading logs. This argument cannot be null.
      maxThreadCount - the maximum number of threads to be executing submitted tasks concurrently. The ThreadPoolTaskExecutor will never execute more tasks concurrently as this number. This argument must be greater than or equal to 1.
      maxQueueSize - the maximum size of the internal queue to store tasks not yet executed due to all threads being busy executing tasks. This argument must be greater than or equal to 1 and is recommended to be (but not required) greater than or equal to maxThreadCount.
      idleTimeout - the time in the given time unit after idle threads should stop. That is if a thread goes idle (i.e.: there are no submitted tasks), it will wait this amount of time before giving up waiting for submitted tasks. The thread may be restarted if needed later. It is recommended to use a reasonably low value for this argument (but not too low), so even if this ThreadPoolTaskExecutor has not been shut down (due to a bug), threads will still terminate allowing the JVM to terminate as well (if there are no more non-daemon threads). This argument must be greater than or equal to zero.
      timeUnit - the time unit of the idleTimeout argument. This argument cannot be null.
      Throws:
      IllegalArgumentException - thrown if an illegal value was specified for any of the int arguments
      NullPointerException - thrown if any of the arguments is null
  • Method Details

    • dontNeedShutdown

      public void dontNeedShutdown()
      Specifies that this ThreadPoolTaskExecutor does not need to be shut down. Calling this method prevents this executor to be shut down automatically when there is no more reference to this executor, which also prevents logging a message if this executor has not been shut down. This method might be called if you do not plan to shutdown this executor but instead want to rely on the threads of this executor to automatically shutdown after a small timeout.
    • setThreadFactory

      public void setThreadFactory(ThreadFactory threadFactory)
      Sets the ThreadFactory which is used to create worker threads for this executor. Already started workers are not affected by this method call but workers created after this method call will use the currently set ThreadFactory.

      It is recommended to call this method before submitting any task to this executor. Doing so guarantees that all worker threads of this executor will be created by the specified ThreadFactory.

      The default ThreadFactory used by this executor is a ExecutorsEx.NamedThreadFactory creating non-daemon threads.

      Parameters:
      threadFactory - the ThreadFactory which is used to create worker threads for this executor. This argument cannot be null.
      Throws:
      NullPointerException - thrown if the specified thread factory is null
    • shutdown

      public void shutdown()
      Shuts down this TaskExecutorService, so that it will not execute tasks submitted to it after this method call returns.

      Already submitted tasks will execute normally but tasks submitted after this method returns will immediately be completed exceptionally with an OperationCanceledException.

      Note that it is possible, that some tasks are submitted concurrently with this call. Those tasks can be either canceled or executed normally, depending on the circumstances.

      If currently executing tasks should be canceled as well, use the TaskExecutorService.shutdownAndCancel() method to shutdown this TaskExecutorService.

      This method call is idempotent. That is, calling it multiple times must have no further effect.

      Specified by:
      shutdown in interface TaskExecutorService
      Overrides:
      shutdown in class DelegatedTaskExecutorService
      See Also:
    • shutdownAndCancel

      public void shutdownAndCancel()
      Shuts down this TaskExecutorService and cancels already submitted tasks, so that it will not execute tasks submitted to it after this method call returns.

      Already submitted tasks will be canceled and the tasks may detect this cancellation request by inspecting their CancellationToken but tasks submitted after this method returns will immediately be completed exceptionally with an OperationCanceledException.

      Note that it is possible, that some tasks are submitted concurrently with this call. Those tasks may be treated as if they were submitted before this method call or as if they were submitted after.

      If currently executing tasks should be left executing, use the TaskExecutorService.shutdown() method instead to shutdown this TaskExecutorService.

      This method call is idempotent. That is, calling it multiple times must have no further effect. Note however, that calling this method after the shutdown() method is meaningful because this method will cancel ongoing tasks.

      Specified by:
      shutdownAndCancel in interface TaskExecutorService
      Overrides:
      shutdownAndCancel in class DelegatedTaskExecutorService
      See Also:
    • getNumberOfQueuedTasks

      public long getNumberOfQueuedTasks()
      Returns the approximate number of tasks currently queued to this executor. The queued tasks are not currently executing but are scheduled to be executed in the future.

      Note that the value returned by this method should be considered unreliable and cannot be used for synchronization purposes.

      Specified by:
      getNumberOfQueuedTasks in interface MonitorableTaskExecutor
      Returns:
      the approximate number of tasks currently queued to this executor. This method always returns a value greater than or equal to zero.
    • getNumberOfExecutingTasks

      public long getNumberOfExecutingTasks()
      Returns the approximate number of tasks currently being executed.

      Note that the value returned by this method should be considered unreliable and cannot be used for synchronization purposes.

      Specified by:
      getNumberOfExecutingTasks in interface MonitorableTaskExecutor
      Returns:
      the approximate number of tasks currently being executed. This method always returns a value greater than or equal to zero.
    • isExecutingInThis

      public boolean isExecutingInThis()
      Returns true if the calling code is executing in the context of this executor. That is, it is executed by a task submitted to this executor.

      This method can be used to check that a method call is executing in the context it was designed for.

      Specified by:
      isExecutingInThis in interface ContextAwareTaskExecutor
      Returns:
      true if the calling code is executing in the context of this executor, false otherwise
    • setMaxThreadCount

      public void setMaxThreadCount(int maxThreadCount)
      Sets the maximum number of threads allowed to execute submitted tasks concurrently.

      Setting this property may not have an immediate effect. Setting it to a higher value as was set previously, will not cause new thread to be started if the internal queue is not empty but subsequent submit and execute methods will detect that they can start new threads. Setting this property to a lower value as was set previously, will not cause threads to stop even if they are currently idle. It just prevents new threads to be created until the number of currently running threads drops below this limit (as threads stop due to too long idle time).

      Note that setting this property before a task was submitted to this ThreadPoolTaskExecutor is guaranteed to have immediate effect.

      Parameters:
      maxThreadCount - the maximum number of threads allowed to be executing submitted tasks concurrently. This argument must be greater than or equal to 1.
      Throws:
      IllegalArgumentException - if the specified maxThreadCount is less than 1
    • getMaxThreadCount

      public int getMaxThreadCount()
      Returns the currently set maximum thread to be used by this executor.

      The return value of this method is for information purpose only. Due to concurrent sets and already started threads, there is no guarantee that the return value is truly being honored at the moment. See setMaxThreadCount for details on how this property works.

      Returns:
      the currently set maximum thread to be used by this executor. This value is always greater than or equal to one.
    • setMaxQueueSize

      public void setMaxQueueSize(int maxQueueSize)
      Sets the maximum number of tasks allowed to be stored in the internal queue.

      Setting this property higher than it was set previously will have an immediate effect and currently blocking submit and execute will recheck if they can add the submitted task to the queue. Setting this property lower, however, will not remove tasks from the queue but will prevent more tasks to be added to the queue before the number of tasks in the queue drops below this limit.

      Parameters:
      maxQueueSize - the maximum number of tasks allowed to be stored in the internal queue. This argument must be greater than or equal to 1.
      Throws:
      IllegalArgumentException - if the specified maxQueueSize is less than 1
    • getMaxQueueSize

      public int getMaxQueueSize()
      Returns the currently set maximum size for the queue of tasks scheduled to be executed.

      The return value of this method is for information purpose only. Due to concurrent sets and already queued tasks, there is no guarantee that the return value is truly being honored at the moment. See setMaxQueueSize for details on how this property works.

      Returns:
      the currently set maximum size for the queue of tasks scheduled to be executed. This value is always greater than or equal to one.
    • setIdleTimeout

      public void setIdleTimeout(long idleTimeout, TimeUnit timeUnit)
      Sets the timeout value after idle threads should terminate. That is, threads will terminate if they waited for at least this much time and there was no submitted task for them to execute.

      Setting this property has an immediate effect.

      Parameters:
      idleTimeout - the timeout value in the given time unit after idle threads should terminate. This argument must be greater than or equal to zero.
      timeUnit - the time unit of the idleTimeout argument. This argument cannot be null.
      Throws:
      IllegalArgumentException - thrown if the specified timeout value is less than zero
      NullPointerException - thrown if the specified time unit argument is null
    • getIdleTimeout

      public long getIdleTimeout(TimeUnit timeUnit)
      Returns the currently set timeout value after idle threads should stop.

      The return value of this method is for information purpose only. Due to concurrent sets, there is no guarantee that the return value is truly being honored at the moment. See setIdleTimeout for details on how this property works.

      Parameters:
      timeUnit - the time unit in which the result is request. This argument cannot be null.
      Returns:
      the currently set timeout value after idle threads should stop. The return value might not be exactly what was set by the previous invocation to setIdleTimeout due to rounding errors. This method always returns a values greater than or equal to zero.
      Throws:
      NullPointerException - thrown if the specified time unit is null
    • getPoolName

      public String getPoolName()
      Returns the name of this ThreadPoolTaskExecutor as specified at construction time.
      Returns:
      the name of this ThreadPoolTaskExecutor as specified at construction time. This method never returns null.
    • toString

      public String toString()
      Returns the string representation of this executor in no particular format.

      This method is intended to be used for debugging only.

      Overrides:
      toString in class DelegatedTaskExecutorService
      Returns:
      the string representation of this object in no particular format. This method never returns null.