Class KeyedSubmitterSchedulerLimiter


  • public class KeyedSubmitterSchedulerLimiter
    extends java.lang.Object
    This is a cross between the KeyDistributedScheduler and a SubmitterSchedulerLimiter. 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, KeyDistributedScheduler is a much better option.

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

    Since:
    4.6.0 (since 4.3.0 at org.threadly.concurrent.limiter)
    • 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.
      SubmitterScheduler getSubmitterSchedulerForKey​(java.lang.Object taskKey)
      Returns a scheduler implementation where all tasks submitted on this scheduler 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 schedule​(java.lang.Object taskKey, java.lang.Runnable task, long delayInMs)
      Schedule a one time task with a given delay.
      void scheduleAtFixedRate​(java.lang.Object taskKey, java.lang.Runnable task, long initialDelay, long period)
      Schedule a fixed rate recurring task to run.
      void scheduleWithFixedDelay​(java.lang.Object taskKey, java.lang.Runnable task, long initialDelay, long recurringDelay)
      Schedule a fixed delay recurring task to run.
      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.
      ListenableFuture<?> submitScheduled​(java.lang.Object taskKey, java.lang.Runnable task, long delayInMs)
      Schedule a task with a given delay.
      <TT> ListenableFuture<TT> submitScheduled​(java.lang.Object taskKey, java.lang.Runnable task, TT result, long delayInMs)
      Schedule a task with a given delay.
      <TT> ListenableFuture<TT> submitScheduled​(java.lang.Object taskKey, java.util.concurrent.Callable<TT> task, long delayInMs)
      Schedule a Callable with a given delay.
      • Methods inherited from class java.lang.Object

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

      • KeyedSubmitterSchedulerLimiter

        public KeyedSubmitterSchedulerLimiter​(SubmitterScheduler scheduler,
                                              int maxConcurrency)
        Construct a new KeyedSubmitterSchedulerLimiter providing only the backing scheduler and the maximum concurrency per unique key. By default this will not rename threads for tasks executing.
        Parameters:
        scheduler - Scheduler to execute and schedule tasks on
        maxConcurrency - Maximum concurrency allowed per task key
      • KeyedSubmitterSchedulerLimiter

        public KeyedSubmitterSchedulerLimiter​(SubmitterScheduler scheduler,
                                              int maxConcurrency,
                                              boolean limitFutureListenersExecution)
        Construct a new KeyedSubmitterSchedulerLimiter providing only the backing scheduler 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:
        scheduler - Scheduler to execute and schedule tasks on
        maxConcurrency - Maximum concurrency allowed per task key
        limitFutureListenersExecution - true to include listener / mapped functions towards execution limit
      • KeyedSubmitterSchedulerLimiter

        public KeyedSubmitterSchedulerLimiter​(SubmitterScheduler scheduler,
                                              int maxConcurrency,
                                              java.lang.String subPoolName,
                                              boolean addKeyToThreadName)
        Construct a new KeyedSubmitterSchedulerLimiter providing the backing scheduler, the maximum concurrency per unique key, and how keyed limiter threads should be named.
        Parameters:
        scheduler - Scheduler to execute and schedule tasks on
        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
      • KeyedSubmitterSchedulerLimiter

        public KeyedSubmitterSchedulerLimiter​(SubmitterScheduler scheduler,
                                              int maxConcurrency,
                                              java.lang.String subPoolName,
                                              boolean addKeyToThreadName,
                                              boolean limitFutureListenersExecution)
        Construct a new KeyedSubmitterSchedulerLimiter providing the backing scheduler, 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:
        scheduler - Scheduler to execute and schedule tasks on
        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

      • submitScheduled

        public ListenableFuture<?> submitScheduled​(java.lang.Object taskKey,
                                                   java.lang.Runnable task,
                                                   long delayInMs)
        Schedule a task with a given delay. There is a slight increase in load when using submitScheduled(Object, Runnable, long) over schedule(Object, Runnable, long). So this should only be used when the future is necessary.

        The Future.get() method will return null once the runnable has completed.

        The key is used to identify this threads execution limit. Tasks with matching keys will be limited concurrent execution to the level returned by getMaxConcurrencyPerKey().

        See also: SubmitterScheduler.submitScheduled(Runnable, long)

        Parameters:
        taskKey - Key to use for identifying execution limit
        task - runnable to execute
        delayInMs - time in milliseconds to wait to execute task
        Returns:
        a future to know when the task has completed
      • submitScheduled

        public <TT> ListenableFuture<TT> submitScheduled​(java.lang.Object taskKey,
                                                         java.lang.Runnable task,
                                                         TT result,
                                                         long delayInMs)
        Schedule a task with a given delay. The Future.get() method will return the provided result once the runnable has completed.

        The key is used to identify this threads execution limit. Tasks with matching keys will be limited concurrent execution to the level returned by getMaxConcurrencyPerKey().

        See also: SubmitterScheduler.submitScheduled(Runnable, Object, long)

        Type Parameters:
        TT - type of result returned from the future
        Parameters:
        taskKey - Key to use for identifying execution limit
        task - runnable to execute
        result - result to be returned from resulting future .get() when runnable completes
        delayInMs - time in milliseconds to wait to execute task
        Returns:
        a future to know when the task has completed
      • submitScheduled

        public <TT> ListenableFuture<TT> submitScheduled​(java.lang.Object taskKey,
                                                         java.util.concurrent.Callable<TT> task,
                                                         long delayInMs)
        Schedule a Callable with a given delay. This is needed when a result needs to be consumed from the callable.

        The key is used to identify this threads execution limit. Tasks with matching keys will be limited concurrent execution to the level returned by getMaxConcurrencyPerKey().

        See also: SubmitterScheduler.submitScheduled(Callable, long)

        Type Parameters:
        TT - type of result returned from the future
        Parameters:
        taskKey - Key to use for identifying execution limit
        task - callable to be executed
        delayInMs - time in milliseconds to wait to execute task
        Returns:
        a future to know when the task has completed and get the result of the callable
      • schedule

        public void schedule​(java.lang.Object taskKey,
                             java.lang.Runnable task,
                             long delayInMs)
        Schedule a one time task with a given delay.

        The key is used to identify this threads execution limit. Tasks with matching keys will be limited concurrent execution to the level returned by getMaxConcurrencyPerKey().

        See also: SubmitterScheduler.schedule(Runnable, long)

        Parameters:
        taskKey - Key to use for identifying execution limit
        task - runnable to execute
        delayInMs - time in milliseconds to wait to execute task
      • scheduleWithFixedDelay

        public void scheduleWithFixedDelay​(java.lang.Object taskKey,
                                           java.lang.Runnable task,
                                           long initialDelay,
                                           long recurringDelay)
        Schedule a fixed delay recurring task to run. The recurring delay time will be from the point where execution has finished. So the execution frequency is the recurringDelay + runtime for the provided task.

        Unlike ScheduledExecutorService if the task throws an exception, subsequent executions are NOT suppressed or prevented. So if the task throws an exception on every run, the task will continue to be executed at the provided recurring delay (possibly throwing an exception on each execution).

        The key is used to identify this threads execution limit. Tasks with matching keys will be limited concurrent execution to the level returned by getMaxConcurrencyPerKey().

        See also: SubmitterScheduler.scheduleWithFixedDelay(Runnable, long, long)

        Parameters:
        taskKey - Key to use for identifying execution limit
        task - runnable to be executed
        initialDelay - delay in milliseconds until first run
        recurringDelay - delay in milliseconds for running task after last finish
      • scheduleAtFixedRate

        public void scheduleAtFixedRate​(java.lang.Object taskKey,
                                        java.lang.Runnable task,
                                        long initialDelay,
                                        long period)
        Schedule a fixed rate recurring task to run. The recurring delay will be the same, regardless of how long task execution takes. A given runnable will not run concurrently (unless it is submitted to the scheduler multiple times). Instead of execution takes longer than the period, the next run will occur immediately (given thread availability in the pool).

        Unlike ScheduledExecutorService if the task throws an exception, subsequent executions are NOT suppressed or prevented. So if the task throws an exception on every run, the task will continue to be executed at the provided recurring delay (possibly throwing an exception on each execution).

        The key is used to identify this threads execution limit. Tasks with matching keys will be limited concurrent execution to the level returned by getMaxConcurrencyPerKey().

        See also: SubmitterScheduler.scheduleAtFixedRate(Runnable, long, long)

        Parameters:
        taskKey - Key to use for identifying execution limit
        task - runnable to be executed
        initialDelay - delay in milliseconds until first run
        period - amount of time in milliseconds between the start of recurring executions
      • getSubmitterSchedulerForKey

        public SubmitterScheduler getSubmitterSchedulerForKey​(java.lang.Object taskKey)
        Returns a scheduler implementation where all tasks submitted on this scheduler 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:
        scheduler which will only execute with reference to the provided key
      • 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