Class KeyedExecutorLimiter


  • public class KeyedExecutorLimiter
    extends java.lang.Object
    This is a cross between the KeyDistributedExecutor and an ExecutorLimiter. This is designed to limit concurrency for a given thread, but permit more than one thread to run at a time for a given key. If the desired effect is to have a single thread per key, KeyDistributedExecutor is a much better option.

    The easiest way to use this class would be to have it distribute out executors through getSubmitterExecutorForKey(Object).

    Since:
    4.6.0 (since 4.3.0 at org.threadly.concurrent.limiter)
    • Constructor Summary

      Constructors 
      Constructor Description
      KeyedExecutorLimiter​(java.util.concurrent.Executor executor, int maxConcurrency)
      Construct a new KeyedExecutorLimiter providing only the backing executor and the maximum concurrency per unique key.
      KeyedExecutorLimiter​(java.util.concurrent.Executor executor, int maxConcurrency, boolean limitFutureListenersExecution)
      Construct a new KeyedExecutorLimiter providing only the backing executor and the maximum concurrency per unique key.
      KeyedExecutorLimiter​(java.util.concurrent.Executor executor, int maxConcurrency, java.lang.String subPoolName, boolean addKeyToThreadName)
      Construct a new KeyedExecutorLimiter providing the backing executor, the maximum concurrency per unique key, and how keyed limiter threads should be named.
      KeyedExecutorLimiter​(java.util.concurrent.Executor executor, int maxConcurrency, java.lang.String subPoolName, boolean addKeyToThreadName, boolean limitFutureListenersExecution)
      Construct a new KeyedExecutorLimiter providing the backing executor, the maximum concurrency per unique key, and how keyed limiter threads should be named.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void execute​(java.lang.Object taskKey, java.lang.Runnable task)
      Provide a task to be run with a given thread key.
      int getMaxConcurrencyPerKey()
      Check how many threads may run in parallel for a single unique key.
      SubmitterExecutor getSubmitterExecutorForKey​(java.lang.Object taskKey)
      Returns an executor implementation where all tasks submitted on this executor will run on the provided key.
      int getTrackedKeyCount()
      Check how many keys are currently being restricted or monitored.
      int getUnsubmittedTaskCount​(java.lang.Object taskKey)
      Check how many tasks are currently being limited, and not submitted yet for a given key.
      java.util.Map<java.lang.Object,​java.lang.Integer> getUnsubmittedTaskCountMap()
      Get a map of all the keys and how many tasks are held back (queued) in each limiter per key.
      void setMaxConcurrencyPerKey​(int maxConcurrency)
      Updates the concurrency limit for each key.
      ListenableFuture<?> submit​(java.lang.Object taskKey, java.lang.Runnable task)
      Submit a task to be run with a given thread key.
      <TT> ListenableFuture<TT> submit​(java.lang.Object taskKey, java.lang.Runnable task, TT result)
      Submit a task to be run with a given thread key.
      <TT> ListenableFuture<TT> submit​(java.lang.Object taskKey, java.util.concurrent.Callable<TT> task)
      Submit a callable to be run with a given thread key.
      • Methods inherited from class java.lang.Object

        equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • KeyedExecutorLimiter

        public KeyedExecutorLimiter​(java.util.concurrent.Executor executor,
                                    int maxConcurrency)
        Construct a new KeyedExecutorLimiter providing only the backing executor and the maximum concurrency per unique key. By default this will not rename threads for tasks executing.
        Parameters:
        executor - Executor to execute tasks on
        maxConcurrency - Maximum concurrency allowed per task key
      • KeyedExecutorLimiter

        public KeyedExecutorLimiter​(java.util.concurrent.Executor executor,
                                    int maxConcurrency,
                                    boolean limitFutureListenersExecution)
        Construct a new KeyedExecutorLimiter providing only the backing executor and the maximum concurrency per unique key. By default this will not rename threads for tasks executing.

        This constructor allows you to specify if listeners / FutureCallback's / functions in ListenableFuture.map(java.util.function.Function) or ListenableFuture.flatMap(java.util.function.Function) should be counted towards the concurrency limit. Specifying false will release the limit as soon as the original task completes. Specifying true will continue to enforce the limit until all listeners (without an executor) complete.

        Parameters:
        executor - Executor to execute tasks on
        maxConcurrency - Maximum concurrency allowed per task key
        limitFutureListenersExecution - true to include listener / mapped functions towards execution limit
      • KeyedExecutorLimiter

        public KeyedExecutorLimiter​(java.util.concurrent.Executor executor,
                                    int maxConcurrency,
                                    java.lang.String subPoolName,
                                    boolean addKeyToThreadName)
        Construct a new KeyedExecutorLimiter providing the backing executor, the maximum concurrency per unique key, and how keyed limiter threads should be named.
        Parameters:
        executor - Executor to execute tasks on to
        maxConcurrency - Maximum concurrency allowed per task key
        subPoolName - Name prefix for sub pools, null to not change thread names
        addKeyToThreadName - If true the key's .toString() will be added in the thread name
      • KeyedExecutorLimiter

        public KeyedExecutorLimiter​(java.util.concurrent.Executor executor,
                                    int maxConcurrency,
                                    java.lang.String subPoolName,
                                    boolean addKeyToThreadName,
                                    boolean limitFutureListenersExecution)
        Construct a new KeyedExecutorLimiter providing the backing executor, the maximum concurrency per unique key, and how keyed limiter threads should be named.

        This constructor allows you to specify if listeners / FutureCallback's / functions in ListenableFuture.map(java.util.function.Function) or ListenableFuture.flatMap(java.util.function.Function) should be counted towards the concurrency limit. Specifying false will release the limit as soon as the original task completes. Specifying true will continue to enforce the limit until all listeners (without an executor) complete.

        Parameters:
        executor - Executor to execute tasks on to
        maxConcurrency - Maximum concurrency allowed per task key
        subPoolName - Name prefix for sub pools, null to not change thread names
        addKeyToThreadName - If true the key's .toString() will be added in the thread name
        limitFutureListenersExecution - true to include listener / mapped functions towards execution limit
    • Method Detail

      • getMaxConcurrencyPerKey

        public int getMaxConcurrencyPerKey()
        Check how many threads may run in parallel for a single unique key.
        Returns:
        maximum concurrent tasks to be run per key
      • setMaxConcurrencyPerKey

        public void setMaxConcurrencyPerKey​(int maxConcurrency)
        Updates the concurrency limit for each key. If reducing the the limit, there will be no attempt or impact on tasks already limiting. Instead new tasks just wont be submitted to the parent pool until existing tasks complete and go below the new limit.
        Parameters:
        maxConcurrency - maximum quantity of tasks to run in parallel per key
        Since:
        5.4
      • getTrackedKeyCount

        public int getTrackedKeyCount()
        Check how many keys are currently being restricted or monitored.
        Returns:
        The number of task keys being monitored
      • getUnsubmittedTaskCount

        public int getUnsubmittedTaskCount​(java.lang.Object taskKey)
        Check how many tasks are currently being limited, and not submitted yet for a given key. This can be useful for knowing how backed up a specific key is.
        Parameters:
        taskKey - Key which would be limited
        Returns:
        Quantity of tasks being held back inside the limiter, and thus still queued
      • getUnsubmittedTaskCountMap

        public java.util.Map<java.lang.Object,​java.lang.Integer> getUnsubmittedTaskCountMap()
        Get a map of all the keys and how many tasks are held back (queued) in each limiter 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 limiters.

        Because this requires an iteration of all limiters, if only a single limiters unsubmitted count is needed, use getUnsubmittedTaskCount(Object) as a cheaper alternative.

        Returns:
        Map of task key's to their respective task queue size
      • execute

        public void execute​(java.lang.Object taskKey,
                            java.lang.Runnable task)
        Provide a task to be run with a given thread key.

        See also: Executor.execute(Runnable)

        Parameters:
        taskKey - object key where equals() will be used to determine execution thread
        task - Task to be executed
      • submit

        public ListenableFuture<?> submit​(java.lang.Object taskKey,
                                          java.lang.Runnable task)
        Submit a task to be run with a given thread key.

        See also: SubmitterExecutor.submit(Runnable)

        Parameters:
        taskKey - object key where equals() will be used to determine execution thread
        task - Task to be executed
        Returns:
        Future to represent when the execution has occurred
      • submit

        public <TT> ListenableFuture<TT> submit​(java.lang.Object taskKey,
                                                java.lang.Runnable task,
                                                TT result)
        Submit a task to be run with a given thread key.

        See also: SubmitterExecutor.submit(Runnable, Object)

        Type Parameters:
        TT - type of result returned from the future
        Parameters:
        taskKey - object key where equals() will be used to determine execution thread
        task - Runnable to be executed
        result - 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 <TT> ListenableFuture<TT> submit​(java.lang.Object taskKey,
                                                java.util.concurrent.Callable<TT> task)
        Submit a callable to be run with a given thread key.

        See also: SubmitterExecutor.submit(Callable)

        Type Parameters:
        TT - type of result returned from the future
        Parameters:
        taskKey - object key where equals() will be used to determine execution thread
        task - Callable to be executed
        Returns:
        Future to represent when the execution has occurred and provide the result from the callable
      • getSubmitterExecutorForKey

        public SubmitterExecutor getSubmitterExecutorForKey​(java.lang.Object taskKey)
        Returns an executor implementation where all tasks submitted on this executor will run on the provided key. Tasks executed on the returned scheduler will be limited by the key submitted on this instance equally with ones provided through the returned instance.
        Parameters:
        taskKey - object key where equals() will be used to determine execution thread
        Returns:
        Executor which will only execute with reference to the provided key