Rate Limiter — Token Bucket Algorithm
Implement a thread-safe rate limiter using the token bucket algorithm for API throttling.
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
public class RateLimiter {
private final long maxTokens;
private final long refillRate; // tokens per second
private long availableTokens;
private long lastRefillTime;
private final ReentrantLock lock = new ReentrantLock();
public RateLimiter(long maxTokens, long refillRate) {
this.maxTokens = maxTokens;
this.refillRate = refillRate;
this.availableTokens = maxTokens;
this.lastRefillTime = System.nanoTime();
}
public boolean tryAcquire() {
return tryAcquire(1);
}
public boolean tryAcquire(int tokens) {
lock.lock();
try {
refill();
if (availableTokens >= tokens) {
availableTokens -= tokens;
return true;
}
return false;
} finally {
lock.unlock();
}
}
private void refill() {
long now = System.nanoTime();
long elapsed = now - lastRefillTime;
long tokensToAdd = elapsed * refillRate / 1_000_000_000L;
if (tokensToAdd > 0) {
availableTokens = Math.min(maxTokens, availableTokens + tokensToAdd);
lastRefillTime = now;
}
}
public long getAvailableTokens() {
lock.lock();
try {
refill();
return availableTokens;
} finally {
lock.unlock();
}
}
// Per-user rate limiter
private static final java.util.concurrent.ConcurrentHashMap<String, RateLimiter> limiters
= new java.util.concurrent.ConcurrentHashMap<>();
public static RateLimiter forUser(String userId) {
return limiters.computeIfAbsent(userId,
k -> new RateLimiter(10, 2)); // 10 burst, 2/sec refill
}
public static void main(String[] args) throws Exception {
RateLimiter limiter = new RateLimiter(5, 1); // 5 burst, 1/sec
for (int i = 0; i < 10; i++) {
boolean allowed = limiter.tryAcquire();
System.out.printf("Request %d: %s (tokens: %d)%n",
i, allowed ? "ALLOWED" : "BLOCKED", limiter.getAvailableTokens());
Thread.sleep(300);
}
}
}Use Cases
- API rate limiting per user or IP
- Throttling outbound requests to external services
- Controlling resource consumption in multi-tenant systems
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
CompletableFuture — Async Programming
Chain async operations with CompletableFuture: thenApply, thenCompose, allOf, and exception handling.
Best for: Parallel API calls to multiple services
Virtual Threads — Lightweight Concurrency
Use Java 21 virtual threads for massive concurrency without thread pool tuning or reactive frameworks.
Best for: High-concurrency web servers handling thousands of requests
ExecutorService — Thread Pool Management
Create and manage thread pools with ExecutorService: fixed, cached, scheduled, and custom pools.
Best for: Managing concurrent task execution
Concurrent Collections — Thread-Safe Maps
Use ConcurrentHashMap, CopyOnWriteArrayList, and BlockingQueue for thread-safe data structures.
Best for: Thread-safe caching in multi-threaded applications