Added getLatestOperation(), widened.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@2071 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -21,15 +21,13 @@
|
|||||||
package com.samskivert.util;
|
package com.samskivert.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A throttle is used to prevent code from attempting a particular
|
* A throttle is used to prevent code from attempting a particular operation too often. Often it is
|
||||||
* operation too often. Often it is desirable to retry an operation under
|
* desirable to retry an operation under failure conditions, but simplistic approaches to retrying
|
||||||
* failure conditions, but simplistic approaches to retrying operations
|
* operations can lead to large numbers of spurious attempts to do something that will obviously
|
||||||
* can lead to large numbers of spurious attempts to do something that
|
* fail. The throttle class provides a mechanism for limiting such attempts by measuring whether or
|
||||||
* will obviously fail. The throttle class provides a mechanism for
|
* not an activity has been performed N times in the last M seconds. The user of the class decides
|
||||||
* limiting such attempts by measuring whether or not an activity has been
|
* the appropriate throttle parameters and then simply calls through to throttle to determine
|
||||||
* performed N times in the last M seconds. The user of the class decides
|
* whether or not to go ahead with the operation.
|
||||||
* the appropriate throttle parameters and then simply calls through to
|
|
||||||
* throttle to determine whether or not to go ahead with the operation.
|
|
||||||
*
|
*
|
||||||
* <p> For example:
|
* <p> For example:
|
||||||
*
|
*
|
||||||
@@ -50,17 +48,14 @@ package com.samskivert.util;
|
|||||||
public class Throttle
|
public class Throttle
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Constructs a new throttle instance that will allow the specified
|
* Constructs a new throttle instance that will allow the specified number of operations to
|
||||||
* number of operations to proceed within the specified period (the
|
* proceed within the specified period (the period is measured in milliseconds).
|
||||||
* period is measured in milliseconds).
|
|
||||||
*
|
*
|
||||||
* <p> As operations and period define a ratio, use the smallest value
|
* <p> As operations and period define a ratio, use the smallest value possible for
|
||||||
* possible for <code>operations</code> as an array is created to
|
* <code>operations</code> as an array is created to track the time at which each operation was
|
||||||
* track the time at which each operation was performed (e.g. use 6
|
* performed (e.g. use 6 ops per 10 seconds rather than 60 ops per 100 seconds if
|
||||||
* ops per 10 seconds rather than 60 ops per 100 seconds if
|
* possible). However, note that you may not always want to reduce the ratio as much as
|
||||||
* possible). However, note that you may not always want to reduce the
|
* possible if you wish to allow bursts of operations up to some large value.
|
||||||
* ratio as much as possible if you wish to allow bursts of operations
|
|
||||||
* up to some large value.
|
|
||||||
*/
|
*/
|
||||||
public Throttle (int operations, long period)
|
public Throttle (int operations, long period)
|
||||||
{
|
{
|
||||||
@@ -69,13 +64,11 @@ public class Throttle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an attempt at an operation and returns true if the
|
* Registers an attempt at an operation and returns true if the operation should be performed
|
||||||
* operation should be performed or false if it should be throttled
|
* or false if it should be throttled (meaning N operations have already been performed in the
|
||||||
* (meaning N operations have already been performed in the last M
|
* last M seconds).
|
||||||
* seconds).
|
|
||||||
*
|
*
|
||||||
* @return true if the throttle is activated, false if the operation
|
* @return true if the throttle is activated, false if the operation can proceed.
|
||||||
* can proceed.
|
|
||||||
*/
|
*/
|
||||||
public boolean throttleOp ()
|
public boolean throttleOp ()
|
||||||
{
|
{
|
||||||
@@ -83,21 +76,16 @@ public class Throttle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an attempt at an operation and returns true if the
|
* Registers an attempt at an operation and returns true if the operation should be performed
|
||||||
* operation should be performed or false if it should be throttled
|
* or false if it should be throttled (meaning N operations have already been performed in the
|
||||||
* (meaning N operations have already been performed in the last M
|
* last M seconds). For systems that don't wish to use {@link System#currentTimeMillis} (opting
|
||||||
* seconds). For systems that don't wish to use {@link
|
* in favor for some custom timing mechanism that is more accurate that {@link
|
||||||
* System#currentTimeMillis} (opting in favor for some custom timing
|
* System#currentTimeMillis}) or those that already have the time, they can avoid an
|
||||||
* mechanism that is more accurate that {@link
|
* unnecessary call to {@link System#currentTimeMillis} by using this version of the method.
|
||||||
* System#currentTimeMillis}) or those that already have the time,
|
|
||||||
* they can avoid an unnecessary call to {@link
|
|
||||||
* System#currentTimeMillis} by using this version of the method.
|
|
||||||
*
|
*
|
||||||
* @param timeStamp the timestamp at which this operation is being
|
* @param timeStamp the timestamp at which this operation is being attempted.
|
||||||
* attempted.
|
|
||||||
*
|
*
|
||||||
* @return true if the throttle is activated, false if the operation
|
* @return true if the throttle is activated, false if the operation can proceed.
|
||||||
* can proceed.
|
|
||||||
*/
|
*/
|
||||||
public boolean throttleOp (long timeStamp)
|
public boolean throttleOp (long timeStamp)
|
||||||
{
|
{
|
||||||
@@ -110,36 +98,42 @@ public class Throttle
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if we would throttle an operation occuring at the specified
|
* Check to see if we would throttle an operation occuring at the specified timestamp.
|
||||||
* timestamp. Typically used in conjunction with {@link #noteOp}.
|
* Typically used in conjunction with {@link #noteOp}.
|
||||||
*/
|
*/
|
||||||
public boolean wouldThrottle (long timeStamp)
|
public boolean wouldThrottle (long timeStamp)
|
||||||
{
|
{
|
||||||
// if the oldest operation was performed less than _period ago, we
|
// if the oldest operation was performed less than _period ago, we need to throttle
|
||||||
// need to throttle
|
|
||||||
long elapsed = timeStamp - _ops[_lastOp];
|
long elapsed = timeStamp - _ops[_lastOp];
|
||||||
// if negative time elapsed, we must be running on windows.
|
// if negative time elapsed, we must be running on windows; let's just cope by not
|
||||||
// Let's just cope by not throttling.
|
// throttling
|
||||||
return (elapsed >= 0 && elapsed < _period);
|
return (elapsed >= 0 && elapsed < _period);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that an operation occurred at the specified timestamp. This
|
* Note that an operation occurred at the specified timestamp. This method should be used with
|
||||||
* method should be used with {@link #wouldThrottle} to note an operation
|
* {@link #wouldThrottle} to note an operation that has already been cleared to
|
||||||
* that has already been cleared to occur. Typically this is used if
|
* occur. Typically this is used if there is another limiting factor besides the throttle that
|
||||||
* there is another limiting factor besides the throttle that determines
|
* determines whether the operation can occur. You are responsible for calling this method in a
|
||||||
* whether the operation can occur. You are responsible for calling this
|
* safe and timely manner after using wouldThrottle.
|
||||||
* method in a safe and timely manner after using wouldThrottle.
|
|
||||||
*/
|
*/
|
||||||
public void noteOp (long timeStamp)
|
public void noteOp (long timeStamp)
|
||||||
{
|
{
|
||||||
// overwrite the oldest operation with the current time
|
// overwrite the oldest operation with the current time and move the oldest operation
|
||||||
// and move the oldest operation pointer to the second oldest
|
// pointer to the second oldest operation (which is now the oldest as we overwrote the
|
||||||
// operation (which is now the oldest as we overwrote the oldest)
|
// oldest)
|
||||||
_ops[_lastOp] = timeStamp;
|
_ops[_lastOp] = timeStamp;
|
||||||
_lastOp = (_lastOp + 1) % _ops.length;
|
_lastOp = (_lastOp + 1) % _ops.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the timestamp of the most recently recorded operation.
|
||||||
|
*/
|
||||||
|
public long getLatestOperation ()
|
||||||
|
{
|
||||||
|
return _ops[(_lastOp + _ops.length - 1) % _ops.length];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for testing.
|
* Used for testing.
|
||||||
*/
|
*/
|
||||||
@@ -148,12 +142,10 @@ public class Throttle
|
|||||||
// set up a throttle for 5 ops per 10 seconds
|
// set up a throttle for 5 ops per 10 seconds
|
||||||
Throttle throttle = new Throttle(5, 10000);
|
Throttle throttle = new Throttle(5, 10000);
|
||||||
|
|
||||||
// try doing one operation per second and we should hit the
|
// try doing one operation per second and we should hit the throttle on the sixth operation
|
||||||
// throttle on the sixth operation and then kick in again on the
|
// and then kick in again on the eleventh, only to stop again on the fifteenth
|
||||||
// eleventh, only to stop again on the fifteenth
|
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
System.out.println((i+1) + ". Throttle: " +
|
System.out.println((i+1) + ". Throttle: " + throttle.throttleOp());
|
||||||
throttle.throttleOp());
|
|
||||||
// pause for a sec
|
// pause for a sec
|
||||||
try { Thread.sleep(1000L); }
|
try { Thread.sleep(1000L); }
|
||||||
catch (InterruptedException ie) {}
|
catch (InterruptedException ie) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user