Class KeyDistributedExecutor
- java.lang.Object
-
- org.threadly.concurrent.wrapper.KeyDistributedExecutor
-
- Direct Known Subclasses:
KeyDistributedScheduler
public class KeyDistributedExecutor extends java.lang.Object
TaskDistributor is designed such that tasks executed on it for a given key will run in a single threaded manner. It needs a multi-threaded pool supplied to it, to then execute those tasks on. While the thread which runs those tasks may be different between multiple executions, no two tasks for the same key will ever be run in parallel.Because of that, it is recommended that the executor provided has as many possible threads as possible keys that could be provided to be run in parallel. If this class is starved for threads some keys may continue to process new tasks, while other keys could be starved.
Assuming that the shared memory (any objects, primitives, etc) are only accessed through the same instance of
KeyDistributedExecutor
, and assuming that those variables are only accessed via the same key. Then the programmer does not need to worry about synchronization, or volatile. TheKeyDistributedExecutor
will ensure the happens-before relationship.- Since:
- 4.6.0 (since 1.0.0 as org.threadly.concurrent.TaskExecutorDistributor)
-
-
Constructor Summary
Constructors Constructor Description KeyDistributedExecutor(java.util.concurrent.Executor executor)
Constructor to use a provided executor implementation for running tasks.KeyDistributedExecutor(java.util.concurrent.Executor executor, boolean accurateQueueSize)
Constructor to use a provided executor implementation for running tasks.KeyDistributedExecutor(java.util.concurrent.Executor executor, int maxTasksPerCycle)
Constructor to use a provided executor implementation for running tasks.KeyDistributedExecutor(java.util.concurrent.Executor executor, int maxTasksPerCycle, boolean accurateQueueSize)
Constructor to use a provided executor implementation for running tasks.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
execute(java.lang.Object threadKey, java.lang.Runnable task)
Provide a task to be run with a given thread key.java.util.concurrent.Executor
getExecutor()
Getter for the executor being used behind the scenes.SubmitterExecutor
getExecutorForKey(java.lang.Object threadKey)
Returns aSubmitterExecutor
implementation where all tasks submitted on this executor will run on the provided key.int
getTaskQueueSize(java.lang.Object threadKey)
Call to check how many tasks have been queued up for a given key.java.util.Map<java.lang.Object,java.lang.Integer>
getTaskQueueSizeMap()
Get a map of all the keys and how many tasks are queued per key.ListenableFuture<?>
submit(java.lang.Object threadKey, java.lang.Runnable task)
Submit a task to be run with a given thread key.<T> ListenableFuture<T>
submit(java.lang.Object threadKey, java.lang.Runnable task, T result)
Submit a task to be run with a given thread key.<T> ListenableFuture<T>
submit(java.lang.Object threadKey, java.util.concurrent.Callable<T> task)
Submit a callable to be run with a given thread key.
-
-
-
Constructor Detail
-
KeyDistributedExecutor
public KeyDistributedExecutor(java.util.concurrent.Executor executor)
Constructor to use a provided executor implementation for running tasks.This constructs with a default expected level of concurrency of 16. This also does not attempt to have an accurate queue size for the
getTaskQueueSize(Object)
call (thus preferring high performance).- Parameters:
executor
- A multi-threaded executor to distribute tasks to. Ideally has as many possible threads as keys that will be used in parallel.
-
KeyDistributedExecutor
public KeyDistributedExecutor(java.util.concurrent.Executor executor, boolean accurateQueueSize)
Constructor to use a provided executor implementation for running tasks.This constructor allows you to specify if you want accurate queue sizes to be tracked for given thread keys. There is a performance hit associated with this, so this should only be enabled if
getTaskQueueSize(Object)
calls will be used.This constructs with a default expected level of concurrency of 16.
- Parameters:
executor
- A multi-threaded executor to distribute tasks to. Ideally has as many possible threads as keys that will be used in parallel.accurateQueueSize
-true
to makegetTaskQueueSize(Object)
more accurate
-
KeyDistributedExecutor
public KeyDistributedExecutor(java.util.concurrent.Executor executor, int maxTasksPerCycle)
Constructor to use a provided executor implementation for running tasks.This constructor allows you to provide a maximum number of tasks for a key before it yields to another key. This can make it more fair, and make it so no single key can starve other keys from running. The lower this is set however, the less efficient it becomes in part because it has to give up the thread and get it again, but also because it must copy the subset of the task queue which it can run.
This also allows you to specify if you want accurate queue sizes to be tracked for given thread keys. There is a performance hit associated with this, so this should only be enabled if
getTaskQueueSize(Object)
calls will be used.This constructs with a default expected level of concurrency of 16. This also does not attempt to have an accurate queue size for the "getTaskQueueSize" call (thus preferring high performance).
- Parameters:
executor
- A multi-threaded executor to distribute tasks to. Ideally has as many possible threads as keys that will be used in parallel.maxTasksPerCycle
- maximum tasks run per key before yielding for other keys
-
KeyDistributedExecutor
public KeyDistributedExecutor(java.util.concurrent.Executor executor, int maxTasksPerCycle, boolean accurateQueueSize)
Constructor to use a provided executor implementation for running tasks.This constructor allows you to provide a maximum number of tasks for a key before it yields to another key. This can make it more fair, and make it so no single key can starve other keys from running. The lower this is set however, the less efficient it becomes in part because it has to give up the thread and get it again, but also because it must copy the subset of the task queue which it can run.
This also allows you to specify if you want accurate queue sizes to be tracked for given thread keys. There is a performance hit associated with this, so this should only be enabled if
getTaskQueueSize(Object)
calls will be used.This constructs with a default expected level of concurrency of 16.
- Parameters:
executor
- A multi-threaded executor to distribute tasks to. Ideally has as many possible threads as keys that will be used in parallel.maxTasksPerCycle
- maximum tasks run per key before yielding for other keysaccurateQueueSize
-true
to makegetTaskQueueSize(Object)
more accurate
-
-
Method Detail
-
getExecutor
public java.util.concurrent.Executor getExecutor()
Getter for the executor being used behind the scenes.- Returns:
- executor tasks are being distributed to
-
getExecutorForKey
public SubmitterExecutor getExecutorForKey(java.lang.Object threadKey)
Returns aSubmitterExecutor
implementation where all tasks submitted on this executor will run on the provided key.- Parameters:
threadKey
- object key where hashCode will be used to determine execution thread- Returns:
- executor which will only execute based on the provided key
-
getTaskQueueSize
public int getTaskQueueSize(java.lang.Object threadKey)
Call to check how many tasks have been queued up for a given key. Depending on what constructor was used, and if atrue
was passed in foraccurateQueueSize
, the accuracy of this call varies dramatically.If
true
was not supplied in the constructor foraccurateQueueSize
, this will only report how many tasks have not been accepted by the worker yet. The accepting of those tasks occur in batches, so this number will vary dramatically (and probably be unusable).So it is highly recommended that if your interested in this functionality you supply a
true
into the constructor.Supplying a
true
foraccurateQueueSize
in the constructor does involve some performance cost, but that overhead should be minimal (just no reason to accept any loss if not interested in this feature).- Parameters:
threadKey
- key for task queue to examine- Returns:
- the number of tasks queued for the key
- Since:
- 1.2.0
-
getTaskQueueSizeMap
public java.util.Map<java.lang.Object,java.lang.Integer> getTaskQueueSizeMap()
Get a map of all the keys and how many tasks are queued per key. This map is generated without locking. Due to that, this may be inaccurate as task queue sizes changed while iterating all key's active workers.Because this requires an iteration of all task workers, if only a single key's queue size is needed, use
getTaskQueueSize(Object)
as a cheaper alternative.If
true
was not supplied in the constructor foraccurateQueueSize
, this will only report how many tasks have not been accepted by the worker yet. The accepting of those tasks occur in batches, so this number will vary dramatically (and probably be unusable).So it is highly recommended that if your interested in this functionality you supply a
true
into the constructor.Supplying a
true
foraccurateQueueSize
in the constructor does involve some performance cost, but that overhead should be minimal (just no reason to accept any loss if not interested in this feature).- Returns:
- Map of task key's to their respective queue size
-
execute
public void execute(java.lang.Object threadKey, java.lang.Runnable task)
Provide a task to be run with a given thread key.- Parameters:
threadKey
- object key whereequals()
will be used to determine execution threadtask
- Task to be executed
-
submit
public ListenableFuture<?> submit(java.lang.Object threadKey, java.lang.Runnable task)
Submit a task to be run with a given thread key.- Parameters:
threadKey
- object key whereequals()
will be used to determine execution threadtask
- Task to be executed- Returns:
- Future to represent when the execution has occurred
-
submit
public <T> ListenableFuture<T> submit(java.lang.Object threadKey, java.lang.Runnable task, T result)
Submit a task to be run with a given thread key.- Type Parameters:
T
- type of result returned from the future- Parameters:
threadKey
- object key whereequals()
will be used to determine execution threadtask
- Runnable to be executedresult
- Result to be returned from future when task completes- Returns:
- Future to represent when the execution has occurred and provide the given result
-
submit
public <T> ListenableFuture<T> submit(java.lang.Object threadKey, java.util.concurrent.Callable<T> task)
Submit a callable to be run with a given thread key.- Type Parameters:
T
- type of result returned from the future- Parameters:
threadKey
- object key whereequals()
will be used to determine execution threadtask
- Callable to be executed- Returns:
- Future to represent when the execution has occurred and provide the result from the callable
-
-