Class FixedRateBarrier

  • All Implemented Interfaces:
    java.io.Serializable

    @ThreadSafety(level=COMPLETELY_THREADSAFE)
    public final class FixedRateBarrier
    extends java.lang.Object
    implements java.io.Serializable
    Instances of this class are used to ensure that certain actions are performed at a fixed rate per interval (e.g. 10000 search operations per second).

    Once a class is constructed with the duration of an interval and the target per interval, the await() method only releases callers at the specified number of times per interval. This class is most useful when the target number per interval exceeds the limits of other approaches such as java.util.Timer or java.util.concurrent.ScheduledThreadPoolExecutor. For instance, this does a good job of ensuring that something happens about 10000 times per second, but it's overkill to ensure something happens five times per hour. This does come at a cost. In the worst case, a single thread is tied up in a loop doing a small amount of computation followed by a Thread.yield(). Calling Thread.sleep() is not possible because many platforms sleep for a minimum of 10ms, and all platforms require sleeping for at least 1ms.

    Testing has shown that this class is accurate for a "no-op" action up to two million per second, which vastly exceeds its typical use in tools such as searchrate and modrate. This class is designed to be called by multiple threads, however, it does not make any fairness guarantee between threads; a single-thread might be released from the await() method many times before another thread that is blocked in that method.

    This class attempts to smooth out the target per interval throughout each interval. At a given ratio, R between 0 and 1, through the interval, the expected number of actions to have been performed in the interval at that time is R times the target per interval. That is, 10% of the way through the interval, approximately 10% of the actions have been performed, and 80% of the way through the interval, 80% of the actions have been performed.

    It's possible to wait for multiple "actions" in one call with await(int). An example use is rate limiting writing bytes out to a file. You could configure a FixedRateBarrier to only allow 1M bytes to be written per second, and then call await(int) with the size of the byte buffer to write. The call to await(int) would block until writing out the buffer would not exceed the desired rate.

    See Also:
    Serialized Form
    • Constructor Summary

      Constructors 
      Constructor Description
      FixedRateBarrier​(long intervalDurationMs, int perInterval)
      Constructs a new FixedRateBarrier, which is active until shutdownRequested is called.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      boolean await()
      This method waits until it is time for the next 'action' to be performed based on the specified interval duration and target per interval.
      boolean await​(int count)
      This method waits until it is time for the next count 'actions' to be performed based on the specified interval duration and target per interval.
      ObjectPair<java.lang.Long,​java.lang.Integer> getTargetRate()
      Retrieves information about the current target rate for this barrier.
      boolean isShutdownRequested()
      Returns true if shutdown has been requested.
      void setRate​(long intervalDurationMs, int perInterval)
      Updates the rates associated with this FixedRateBarrier.
      void shutdownRequested()
      Shuts down this barrier.
      • Methods inherited from class java.lang.Object

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

      • FixedRateBarrier

        public FixedRateBarrier​(long intervalDurationMs,
                                int perInterval)
        Constructs a new FixedRateBarrier, which is active until shutdownRequested is called.
        Parameters:
        intervalDurationMs - The duration of the interval in milliseconds.
        perInterval - The target number of times that await() should return per interval.
    • Method Detail

      • setRate

        public void setRate​(long intervalDurationMs,
                            int perInterval)
        Updates the rates associated with this FixedRateBarrier. The new rate will be in effect when this method returns.
        Parameters:
        intervalDurationMs - The duration of the interval in milliseconds.
        perInterval - The target number of times that await() should return per interval.
      • await

        public boolean await()
        This method waits until it is time for the next 'action' to be performed based on the specified interval duration and target per interval. This method can be called by multiple threads simultaneously. This method returns immediately if shutdown has been requested.
        Returns:
        true if shutdown has been requested and false otherwise.
      • await

        public boolean await​(int count)
        This method waits until it is time for the next count 'actions' to be performed based on the specified interval duration and target per interval. To achieve the target rate, it's recommended that on average count is small relative to perInterval (and the count must not be larger than perInterval). A count value will not be split across intervals, and due to timing issues, it's possible that a count that barely fits in the current interval will need to wait until the next interval. If it's not possible to use smaller 'count' values, then increase perInterval and intervalDurationMs by the same relative amount. As an example, if count is on average 1/10 as big as perInterval, then you can expect to attain 90% of the target rate. Increasing perInterval and intervalDurationMs by 10x means that 99% of the target rate can be achieved.

        This method can be called by multiple threads simultaneously. This method returns immediately if shutdown has been requested.

        Parameters:
        count - The number of 'actions' being performed. It must be less than or equal to perInterval, and is recommended to be fairly small relative to perInterval so that it is easier to achieve the desired rate and exhibit smoother performance.
        Returns:
        true if shutdown has been requested and false otherwise.
      • getTargetRate

        public ObjectPair<java.lang.Long,​java.lang.Integer> getTargetRate()
        Retrieves information about the current target rate for this barrier. The value returned will include a Long that specifies the duration of the current interval in milliseconds and an Integer that specifies the number of times that the await() method should return per interval.
        Returns:
        Information about hte current target rate for this barrier.
      • shutdownRequested

        public void shutdownRequested()
        Shuts down this barrier. Future calls to await() will return immediately.
      • isShutdownRequested

        public boolean isShutdownRequested()
        Returns true if shutdown has been requested.
        Returns:
        true if shutdown has been requested and false otherwise.