public final class DynamicThreadPool<Target extends Runnable>
extends Object
implements Runnable
The internal flow of a DynamicThreadPool has three required components, the Dispatcher (assigns new Threads from the Pool), the Pool (where all the Threads reside), and the Manager (which cleans up Threads), plus one more optional component, the Skulker (for delayed clean-up to be handled late without consuming pool Threads for extended durations):
+--------[Dispatcher]--+ +--------------[Pool]--+ | | | | | * Passes object to | | * Contains variable | | next available | | number of threads | | Thread, and | | | | updates the queue | | * Statistical data | | | | is derived from | | * Returns assigned | | the ThreadPool for | | Thread object to | | the Queue Manager | | the caller |<--->| for maintenance | | | | | +----------------------+ | * Lists of Threads, | | | their States, and | V | other custom | +-----------[Manager]--+ | information, are | | | | obtainable via the | | * Handles Thread |<--->| list() accessor | | recycling upon | | | | thread termination | +----------------------+ | one at a time, in | | order to prevent | | performance issues | +-----------[Skulker]--+ | | | | | * Dynamically alters | | * Optional thread | | size of ThreadPool | | for additional | | as per policies | | clean-up (e.g., | | defined during | | closing lingering | | initialization |---->| sockets) | | | | | +----------------------+ +----------------------+ |
Policies may be set with a Constructor, and/or with modifier methods. At least 1 thread is assigned to the Pool (p), plus 1 thread is assigned to the Manager, plus 1 thread is assigned to the Skulker (if defined), thus the minimum number of threads per DynamicThreadPool is p+1 or p+1+1. These threads are all members of the same ThreadGroup, which is assigned the same name as that of the DynamicThreadPool it belongs to.
The Dispatcher's job is to take the next available (unused/free) thread and store the passed object in it, then unsuspend the thread and return the reference to it to the caller (an example of use of the dispatch() method is a loop that accepts inbound internet connections, and uses separate threads to handle each request). The Dispatcher also notifies the Manager when more threads are needed.
The Manager is responsible for creating and deleting threads as per defined policies (the DynamicThreadPool's Constructor blocks during the creation of the required minimum number of threads, then returns while the Manager continues in parallel to create any additionally needed threads). The Manager thread's priority can be set independently from the default for the Pool, and handles its workload sequentially in a prioritized-queue fashion.
The Skulker, if defined, consumes one additional thread that gracefully completes the termination of whatever resources the Thread no longer needs (e.g., a Socket that was shut down but must exist until after the other end signals termination or an arbitrary time limit expires). The thread either passes this information directly to the Skulker at any time, and/or to the thread termination method (which in turn can pass this information directly to the Skulker), and informs the Manager to unsuspend the Skulker to deal with the new resources. This frees up the thread for re-assignment by the Dispatcher as needed, while also reducing demand for system resources.
Modifier and Type | Field and Description |
---|---|
static String |
VERSION
Version number of this Package (read-only).
|
Constructor and Description |
---|
DynamicThreadPool(Class<Target> poolThread,
String poolName)
Create a DynamicThreadPool with a default of a minimum of 10 threads, and
a maximum of 100 threads.
|
DynamicThreadPool(Class<Target> poolThread,
String poolName,
int threads)
Create a DynamicThreadPool with minimum and maximum numbers of threads
that are equal.
|
DynamicThreadPool(Class<Target> poolThread,
String poolName,
int minimumThreads,
int maximumThreads)
Create a DynamicThreadPool with specific minimum and maximum numbers of
threads.
|
DynamicThreadPool(Class<Target> poolThread,
String poolName,
int minimumThreads,
int maximumThreads,
int spareThreads)
Create a DynamicThreadPool with a minimum number of threads, a maximum
number of threads, and matching minimum and maximum numbers of spare
threads.
|
DynamicThreadPool(Class<Target> poolThread,
String poolName,
int minimumThreads,
int maximumThreads,
int minimumSpareThreads,
int maximumSpareThreads)
Create a DynamicThreadPool with minimum and maximum numbers of threads,
and the minimum number of spare threads.
|
Modifier and Type | Method and Description |
---|---|
boolean |
addThread()
Increase the size of the ThreadPool by one thread.
|
int |
addThreads(int numberOfThreads)
Increase the size of the DynamicThreadPool by the specified number of
threads.
|
DynamicThread |
dispatch()
Dispatches the next available thread in the pool.
|
boolean |
getDebugMode()
Gets the current debugging output mode.
|
DynamicThread |
getDynamicThread(long poolID)
Returns the DynamicThread Object associated with the specified ID number.
|
int |
getManagerPriority()
Returns the priority of the Manager thread.
|
int |
getPoolAttenuationDecay()
Returns the "pool attenuation decay" setting.
|
long |
getPoolAttenuationDelay()
Returns the "pool attenuation delay" setting.
|
long |
getPoolMaintenanceDelay()
Returns the "pool maintenance delay" setting.
|
int |
getSkulkerPriority()
Returns the priority of the Skulker thread.
|
Thread |
getSkulkerThread()
Gets the Thread object that the Skulker was associated with.
|
int |
getSpareThreadIncrement()
Returns the "spare thread increment" setting.
|
long |
getThreadDestructionDelay()
Returns the "thread destruction delay" setting.
|
int[] |
getThreadLimits()
Returns an int[] array containing thread and spare thread limit settings:
|
int |
getThreadPriority()
Returns the priority used when creating new pool threads.
|
int |
getThreadResetPriority()
Returns the priority used when resetting ReRunnable pool threads.
|
boolean |
isReRunnable()
Indicates if the Target implements the ReRunnable interface (the Target
must implement either the Runnable or the ReRunnable interface).
|
void |
killThread(long poolID)
Forcefully stop a thread and delete it from the pool, no matter what it's
doing (this is not graceful; the removeThread() method is preferred).
|
Object |
popSkulker()
Pops an object off of the queue for the Skulker.
|
void |
pushSkulker(Object... objects)
Pushes objects onto the queue for the Skulker to process later.
|
boolean |
removeThread()
Decreases the size of the pool by one thread.
|
int |
removeThreads(int numberOfThreads)
Decreases the size of the DynamicThreadPool by the specified number of
threads.
|
boolean |
setDebugMode(boolean debuggingOutputMode)
Sets the current debugging output mode.
|
void |
setManagerPriority(int priority)
Sets the priority of the Manager thread.
|
void |
setManagerStackSize(long stackSize)
Sets the size of the stack for the manager thread.
|
void |
setMaximumDispatchesPerThread(long maximum)
Specifies the maximum number of times a ReRunnable target can be re-run
before it is destroyed.
|
void |
setMaximumExceptionsPerThread(long maximum)
Specifies the maximum number of times a ReRunnable target can throw an
uncaught exception before it is destroyed.
|
void |
setMaximumSpareThreads(int spareThreads)
Defines the maximum number of spare threads that may be in the pool.
|
void |
setMaximumThreads(int threads)
Defines the absolute maximum number of threads that may be in the pool,
regardless of their status.
|
void |
setMinimumSpareThreads(int spareThreads)
Defines the minimum number of spare threads that must be in the pool.
|
void |
setMinimumThreads(int threads)
Defines the absolute minimum number of threads that must be in the pool,
regardless of their status.
|
void |
setPoolAttenuationDecay(int threads)
Sets the maximum number of threads that will be removed when attenuation
is attempted.
|
void |
setPoolAttenuationDelay(long milliseconds)
Sets the amount of time the Manager will wait before decreasing the size
of the pool when there are too many spare threads.
|
void |
setPoolMaintenanceDelay(long milliseconds)
Sets the amount of time the Manager will wait after thread termination
activity to perform pool size maintainance one time.
|
void |
setResetAfterFinalDispatch(boolean resetFlag)
Specifies if the ReRunnable target's reset() method will be called after
the final re-run.
|
void |
setSkulkerPriority(int priority)
Sets the priority of the Skulker thread.
|
void |
setSkulkerRunnable(Runnable skulker)
Sets the Runnable Skulker thread object.
|
void |
setSkulkerStackSize(long stackSize)
Sets the size of the stack for the skulker thread.
|
void |
setSpareThreadIncrement(int threads)
Sets the minimum number of threads that will be created when the number
of number of available spare threads falls below the minimum.
|
void |
setSpareThreadLimits(int minimumSpareThreads,
int maximumSpareThreads)
Defines the minimum and maximum number of spare threads.
|
void |
setThreadDestructionDelay(long milliseconds)
Sets the amount of time a DynamicThread will sleep after terminating, but
before self-destructing.
|
void |
setThreadLimits(int minimumThreads,
int maximumThreads)
Defines the absolute minimum and maximum numbers of threads.
|
void |
setThreadNamePrefix(String prefix)
Sets the prefix to use in the name when creating new pool threads.
|
void |
setThreadNameSuffix(String suffix)
Sets the suffix to use in the name when creating new pool threads.
|
int |
setThreadPriority(int priority)
Sets the priority to use when creating new pool threads, and updates the
priority for all threads in the pool that are in a "ready" state.
|
void |
setThreadResetPriority(int priority)
Sets the priority to use with ReRunnable threads during the reset stage.
|
void |
setThreadStackSize(long stackSize)
Sets the size of the stack for new pool threads.
|
DynamicThreadPool<Target> |
start()
Starts the DynamicThreadPool.
|
public static final String VERSION
public DynamicThreadPool(Class<Target> poolThread, String poolName) throws InstantiationException, IllegalAccessException
The poolThread class that implement either the "java.lang.Runnable" or the "ca.randolf.lang.ReRunnable" interfaces. If there is a need to re-run a thread before destroying it (which can help to reduce the overhead associated with repeated thread destruction and re-creation in high-volume dispatch scenarios), then the ReRunnable interface will enables the ability to dynamically restart a Thread after it finishes running.
poolThread
- A class that extends java.lang.Thread that will be used to
populate the pool (add ".class" to your publicly declared thread class when
specifying it here)poolName
- The name to be associated with the DynamicThreadPool (this
name will also be assigned to the associated ThreadGroup). Pool names must
begin with a letter, may contain letters, digits, or hyphens, and end with
either a letter or a digit.IllegalAccessException
- if a public constructor (with no
arguments) in/or the target class is not accessibleInstantiationException
- if a public constructor (with no
arguments) in the target class isn't definedpublic DynamicThreadPool(Class<Target> poolThread, String poolName, int threads) throws InstantiationException, IllegalAccessException
The poolThread class that implement either the "java.lang.Runnable" or the "ca.randolf.lang.ReRunnable" interfaces. If there is a need to re-run a thread before destroying it (which can help to reduce the overhead associated with repeated thread destruction and re-creation in high-volume dispatch scenarios), then the ReRunnable interface will enables the ability to dynamically restart a Thread after it finishes running.
poolThread
- A class that extends java.lang.Thread that will be used to
populate the pool (add ".class" to your publicly declared thread class when
specifying it here)poolName
- The name to be associated with the DynamicThreadPool (this
name will also be assigned to the associated ThreadGroup). Pool names must
begin with a letter, may contain letters, digits, or hyphens, and end with
either a letter or a digit.threads
- Both the minimum and maximum number of threadsIllegalAccessException
- if a public constructor (with no
arguments) in/or the target class is not accessibleInstantiationException
- if a public constructor (with no
arguments) in the target class isn't definedpublic DynamicThreadPool(Class<Target> poolThread, String poolName, int minimumThreads, int maximumThreads) throws InstantiationException, IllegalAccessException
The poolThread class that implement either the "java.lang.Runnable" or the "ca.randolf.lang.ReRunnable" interfaces. If there is a need to re-run a thread before destroying it (which can help to reduce the overhead associated with repeated thread destruction and re-creation in high-volume dispatch scenarios), then the ReRunnable interface will enables the ability to dynamically restart a Thread after it finishes running.
poolThread
- A class that extends java.lang.Thread that will be used to
populate the pool (add ".class" to your publicly declared thread class when
specifying it here)poolName
- The name to be associated with the DynamicThreadPool (this
name will also be assigned to the associated ThreadGroup). Pool names must
begin with a letter, may contain letters, digits, or hyphens, and end with
either a letter or a digit.minimumThreads
- The minimum number of threads in the poolmaximumThreads
- The maximum number of threads in the poolIllegalAccessException
- if a public constructor (with no
arguments) in/or the target class is not accessibleInstantiationException
- if a public constructor (with no
arguments) in the target class isn't definedpublic DynamicThreadPool(Class<Target> poolThread, String poolName, int minimumThreads, int maximumThreads, int spareThreads) throws InstantiationException, IllegalAccessException
The poolThread class that implement either the "java.lang.Runnable" or the "ca.randolf.lang.ReRunnable" interfaces. If there is a need to re-run a thread before destroying it (which can help to reduce the overhead associated with repeated thread destruction and re-creation in high-volume dispatch scenarios), then the ReRunnable interface will enables the ability to dynamically restart a Thread after it finishes running.
poolThread
- A class that extends java.lang.Thread that will be used to
populate the pool (add ".class" to your publicly declared thread class when
specifying it here)poolName
- The name to be associated with the DynamicThreadPool (this
name will also be assigned to the associated ThreadGroup). Pool names must
begin with a letter, may contain letters, digits, or hyphens, and end with
either a letter or a digit.minimumThreads
- The minimum number of threads in the poolmaximumThreads
- The maximum number of threads in the poolspareThreads
- The matching minimum and maximum number of spare
threadsIllegalAccessException
- if a public constructor (with no
arguments) in/or the target class is not accessibleInstantiationException
- if a public constructor (with no
arguments) in the target class isn't definedpublic DynamicThreadPool(Class<Target> poolThread, String poolName, int minimumThreads, int maximumThreads, int minimumSpareThreads, int maximumSpareThreads) throws InstantiationException, IllegalAccessException
The poolThread class that implement either the "java.lang.Runnable" or the "ca.randolf.lang.ReRunnable" interfaces. If there is a need to re-run a thread before destroying it (which can help to reduce the overhead associated with repeated thread destruction and re-creation in high-volume dispatch scenarios), then the ReRunnable interface will enables the ability to dynamically restart a Thread after it finishes running.
poolThread
- A class that extends java.lang.Thread that will be used to
populate the pool (add ".class" to your publicly declared thread class when
specifying it here)poolName
- The name to be associated with the DynamicThreadPool (this
name will also be assigned to the associated ThreadGroup). Pool names must
begin with a letter, may contain letters, digits, or hyphens, and end with
either a letter or a digit.minimumThreads
- The minimum number of threads in the poolmaximumThreads
- The maximum number of threads in the poolminimumSpareThreads
- The minimum number of unused threads (as
maintained by the Manager)maximumSpareThreads
- The maximum number of unused threads (as
maintained by the Manager)IllegalAccessException
- if a public constructor (with no
arguments) in/or the target class is not accessibleInstantiationException
- if a public constructor (with no
arguments) in the target class isn't definedpublic boolean addThread()
This method is intended for internal use.
addThreads(int)
public int addThreads(int numberOfThreads)
This method is intended for internal use.
numberOfThreads
- Number of threads to add (must be a positive number)addThread()
public DynamicThread dispatch()
The thread is not actually started because additional modifier methods may need to be used by the caller prior to actually starting the target Thread (e.g., the caller may need to supply a Socket object to the Runnable target before starting the thread).
public boolean getDebugMode()
setDebugMode(boolean)
public DynamicThread getDynamicThread(long poolID)
poolID
- DynamicThreadPool ID numberpublic int getManagerPriority()
public int getPoolAttenuationDecay()
public long getPoolAttenuationDelay()
public long getPoolMaintenanceDelay()
public int getSkulkerPriority()
public Thread getSkulkerThread()
public int getSpareThreadIncrement()
public long getThreadDestructionDelay()
public int[] getThreadLimits()
public int getThreadPriority()
public int getThreadResetPriority()
public boolean isReRunnable()
public void killThread(long poolID)
removeThread()
,
removeThreads(int)
public Object popSkulker()
pushSkulker(java.lang.Object...)
public void pushSkulker(Object... objects)
objects
- Any number of objectspopSkulker()
public boolean removeThread()
killThread(long)
,
removeThreads(int)
public int removeThreads(int numberOfThreads)
numberOfThreads
- Number of threads to remove (must be a positive
number)killThread(long)
,
removeThread()
public boolean setDebugMode(boolean debuggingOutputMode)
getDebugMode()
public void setManagerPriority(int priority)
By default, a priority of java.lang.Thread.NORM_PRIORITY is used.
priority
- The new priority (see java.lang.Thread.setPriority() for
information about valid priority levels)public void setManagerStackSize(long stackSize)
stackSize
- the desired stack size (or 0 for the JVM default)setSkulkerStackSize(long)
,
setThreadStackSize(long)
public void setMaximumDispatchesPerThread(long maximum)
This parameter can only be used if the Target implements the ReRunnable interface.
maximum
- New dispatch limitClassCastException
- If the ReRunnable interface is not
implemented by the Target.public void setMaximumExceptionsPerThread(long maximum)
If a target throws an uncaught exception, its DynamicThread is terminated as if it terminated normally, except that an additional statistic is updated that keeps track of the total number of uncaught exceptions that were thrown by pool threads since the DynamicThreadPool was started.
This parameter can only be used if the Target implements the ReRunnable interface.
maximum
- New uncaught exception limitClassCastException
- If the ReRunnable interface is not
implemented by the Target.public void setMaximumSpareThreads(int spareThreads)
When a thread terminates, the manager wakes up, calls Thread.yield() once, then removes threads if the number of spare threads is above this value.
If the maximum number of spare threads is set to be less than the minimum after the pool manager was started, then it will be increased automatically to match this new minimum.
spareThreads
- The minimum number of spare threads (must be greater than
or equal to zero)setMinimumSpareThreads(int)
,
setSpareThreadLimits(int, int)
public void setMaximumThreads(int threads)
If the minimum number of threads is set to be greater than the maximum after the pool manager was started, then it will be decreased automatically to match this new maximum.
threads
- The minimum number of threadssetMinimumThreads(int)
,
setThreadLimits(int, int)
public void setMinimumSpareThreads(int spareThreads)
When a thread terminates, the manager wakes up, calls Thread.yield() once, then adds more threads if the number of spare threads is below this value.
If the maximum number of spare threads is set to be less than the minimum after the pool manager was started, then it will be increased automatically to match this new minimum.
spareThreads
- The minimum number of spare threads (must be greater than
or equal to zero)setMaximumSpareThreads(int)
,
setSpareThreadLimits(int, int)
public void setMinimumThreads(int threads)
When the start() method is called, this number of threads is created before the thread pool manager is started.
If the maximum number of threads is set to be less than the minimum after the pool manager was started, then it will be increased automatically to match this new minimum.
threads
- The minimum number of threads (must be greater than zero)setMaximumThreads(int)
,
setThreadLimits(int, int)
public void setPoolAttenuationDecay(int threads)
threads
- Number of threads (must be greater than zero)public void setPoolAttenuationDelay(long milliseconds)
"Pool attenuation delay" is an advanced performance tuning feature that can be useful in scenarios where the pool size cycles dramatically during very short periods of time.
With an increased delay, the Manager will wait before removing threads that would normally be destroyed in accordance with the maximumSpareThreads setting, thus reducing the potential workload of the JVM's memory management functions.
milliseconds
- The delay timepublic void setPoolMaintenanceDelay(long milliseconds)
"Pool maintenance delay" is a memory management tuning feature that ensures the thread pool isn't consuming unused threads as it waits for additional threads to self-terminate.
When the "pool attenuation delay" is specified, setting the "pool maintenance delay" to an equal or greater value is recommended to ensure that the maintenance cycle won't be inhibited by pool attenuation.
Additional thread terminations will trigger maintenance to be rescheduled automatically.
milliseconds
- The delay timepublic void setResetAfterFinalDispatch(boolean resetFlag)
This is useful when the reset() method is to be used as a clean-up routine that kicks in even after an uncaught exception was thrown (similar to the "finally" portion of a "try...catch" block, except with no provision to determine if and where such an exception occurred).
This parameter can only be used if the Target implements the ReRunnable interface.
resetFlag
- ClassCastException
- If the ReRunnable interface is not
implemented by the Target.public void setSkulkerPriority(int priority)
By default, a priority of "java.lang.Thread.NORM_PRIORITY - 1" is used.
priority
- The new priority (see java.lang.Thread.setPriority() for
information about valid priority levels)public void setSkulkerRunnable(Runnable skulker)
skulker
- The Runnable object to use for the Skulker threadpublic void setSkulkerStackSize(long stackSize)
stackSize
- the desired stack size (or 0 for the JVM default)setManagerStackSize(long)
,
setThreadStackSize(long)
public void setSpareThreadIncrement(int threads)
threads
- Number of threads (must be greater than zero)public void setSpareThreadLimits(int minimumSpareThreads, int maximumSpareThreads)
When a thread terminates, the manager wakes up, calls Thread.yield() once, then adds or removes threads if the number of spare threads is below or above the specified ranges respectively.
If the maximum number of spare threads is set to be less than the minimum after the pool manager was started, then it will be increased automatically to match the new minimum.
minimumSpareThreads
- The minimum number of spare threads (must be
greater than or equal to zero)maximumSpareThreads
- The maximum numbe rof spare threads (must be
greater than or equal to zero)setMaximumSpareThreads(int)
,
setMinimumSpareThreads(int)
public void setThreadDestructionDelay(long milliseconds)
For ReRunnable threads, note that this delay only occurs after all re-runs have been exhausted.
"Thread destruction delay" is an advanced performance tuning feature that allows for the "procrastination" of thread destruction after termination, which is especially useful if thread destruction needs to be delayed to reduce CPU Utilization spikes due to pending disk writes being processed in parallel, the Skulker thread has a lot of work to do, etc.
milliseconds
- The delay timepublic void setThreadLimits(int minimumThreads, int maximumThreads)
If the maximum number of threads is set to be less than the minimum after the pool manager was started, then it will be increased automatically to match the new minimum.
minimumThreads
- The minimum number of threadsmaximumThreads
- The maximum number of threadssetMaximumThreads(int)
,
setMinimumThreads(int)
public void setThreadNamePrefix(String prefix)
Each thread is named with an optional prefix, a number (determined at the time of creation), and an optional suffix.
prefix
- The prefix (or null to clear)setThreadNameSuffix(java.lang.String)
public void setThreadNameSuffix(String suffix)
Each thread is named with an optional prefix, a number (determined at the time of creation), and an optional suffix.
suffix
- The suffix (or null to clear)setThreadNamePrefix(java.lang.String)
public int setThreadPriority(int priority)
By default, a priority of java.lang.Thread.NORM_PRIORITY is used.
Threads that have already been dispatched will not be effected by this method, so if this method is executed prior to any dispatches, then all new and existing threads will receive this priority.
priority
- The new default priority (see java.lang.Thread.setPriority()
for information about valid priority levels)public void setThreadResetPriority(int priority)
By default, a priority of java.lang.Thread.NORM_PRIORITY is used.
priority
- The new default priority (see java.lang.Thread.setPriority()
for information about valid priority levels)public void setThreadStackSize(long stackSize)
When using a custom stack size, this method should be used prior to calling the start() method, or else the base set of threads will be created with the JVM default stack size.
stackSize
- the desired stack size (or 0 for the JVM default)setManagerStackSize(long)
,
setSkulkerStackSize(long)
public DynamicThreadPool<Target> start()
As a convenience, this method returns a reference to itself (just like a constructor does) so that ".start()" can simply be included immediately after the constructor.