Created
March 21, 2017 11:04
-
-
Save vladimir-bukhtoyarov/dfe0efdbefc330aea06c662b2042a4ec to your computer and use it in GitHub Desktop.
Naive solution for rate limiting. Please use bucket4j instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.LinkedList; | |
/** | |
* The naive solution for rate limiter which potentially leads to crash JVM with out of memory error. | |
*/ | |
public class NaiveRateLimiter { | |
private long availableTokens; | |
private final long periodMillis; | |
private LinkedList<Issue> issuedTokens = new LinkedList<>(); | |
/** | |
* Creates instance of rate limiter which provides guarantee that consumption rate will be >= tokens/periodMillis | |
*/ | |
public NaiveRateLimiter(long tokens, long periodMillis) { | |
this.availableTokens = tokens; | |
this.periodMillis = periodMillis; | |
} | |
synchronized public boolean tryConsume(int numberTokens) { | |
long nowMillis = System.currentTimeMillis(); | |
clearObsoleteIssues(nowMillis); | |
if (availableTokens < numberTokens) { | |
// has no requested tokens in the bucket | |
return false; | |
} else { | |
issuedTokens.addLast(new Issue(numberTokens, nowMillis)); | |
availableTokens -= numberTokens; | |
return true; | |
} | |
} | |
private void clearObsoleteIssues(long nowMillis) { | |
while (!issuedTokens.isEmpty()) { | |
Issue issue = issuedTokens.getFirst(); | |
if (nowMillis - issue.timestampMillis > periodMillis) { | |
availableTokens += issue.tokens; | |
issuedTokens.removeFirst(); | |
} else { | |
return; | |
} | |
} | |
} | |
private static final class Issue { | |
private final long tokens; | |
private final long timestampMillis; | |
private Issue(long tokens, long timestampMillis) { | |
this.tokens = tokens; | |
this.timestampMillis = timestampMillis; | |
} | |
} | |
private static final class Selftest { | |
public static void main(String[] args) { | |
// 100 tokens per 1 second | |
NaiveRateLimiter limiter = new NaiveRateLimiter(100, 1000); | |
long startMillis = System.currentTimeMillis(); | |
long consumed = 0; | |
while (System.currentTimeMillis() - startMillis < 10000) { | |
if (limiter.tryConsume(1)) { | |
consumed++; | |
} | |
} | |
System.out.println(consumed); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment