本文目录导读:

截至2025年5月,Java标准库(JDK)中没有内置现成的令牌桶(Token Bucket)算法API,但可以通过以下几种方式实现:
使用第三方库(推荐)
Google Guava(最常用)
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.2.0-jre</version>
</dependency>
// 创建令牌桶 - 每秒2个令牌 RateLimiter limiter = RateLimiter.create(2.0); // 每秒产生2个令牌 // 尝试获取令牌(阻塞) double waitTime = limiter.acquire(); // 获取1个令牌,等待直到获取成功 // 尝试获取令牌(非阻塞) boolean acquired = limiter.tryAcquire(); // 立即返回 boolean acquired = limiter.tryAcquire(5, TimeUnit.SECONDS); // 最多等待5秒
Guava RateLimiter 特点
- 基于令牌桶算法(实际上是漏斗算法的变体)
- 支持平滑突发(SmoothBursty)和预热(SmoothWarmingUp)
- 支持预消费
自己实现(简单示例)
public class TokenBucket {
private final long capacity; // 桶容量
private final double refillRate; // 每秒生成的令牌数
private double tokens; // 当前令牌数
private long lastRefillTimestamp; // 上次刷新时间
public TokenBucket(long capacity, double refillRate) {
this.capacity = capacity;
this.refillRate = refillRate;
this.tokens = capacity;
this.lastRefillTimestamp = System.nanoTime();
}
public synchronized boolean tryConsume(int tokens) {
refill();
if (this.tokens >= tokens) {
this.tokens -= tokens;
return true;
}
return false;
}
private void refill() {
long now = System.nanoTime();
double tokensToAdd = (now - lastRefillTimestamp) * refillRate / 1_000_000_000.0;
this.tokens = Math.min(capacity, this.tokens + tokensToAdd);
this.lastRefillTimestamp = now;
}
}
// 使用
TokenBucket bucket = new TokenBucket(10, 2); // 容量10,每秒2个令牌
boolean success = bucket.tryConsume(1); // 尝试获取1个令牌
使用 Java 并发工具 + 定时器
public class TokenBucketScheduled {
private final BlockingQueue<Object> bucket;
private final Object token = new Object();
public TokenBucketScheduled(int capacity, int rate) {
bucket = new LinkedBlockingQueue<>(capacity);
// 初始化装满令牌
for (int i = 0; i < capacity; i++) {
bucket.offer(token);
}
// 定时向桶中添加令牌
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
bucket.offer(token); // 桶满时丢弃
}, 0, 1000 / rate, TimeUnit.MILLISECONDS);
}
public boolean tryConsume() {
return bucket.poll() != null; // 非阻塞
}
public void consume() throws InterruptedException {
bucket.take(); // 阻塞等待
}
}
企业级方案
Resilience4j(支持令牌桶)
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-ratelimiter</artifactId>
<version>2.2.0</version>
</dependency>
RateLimiterConfig config = RateLimiterConfig.custom()
.limitForPeriod(10) // 周期内允许的请求数
.limitRefreshPeriod(Duration.ofSeconds(1)) // 刷新周期
.timeoutDuration(Duration.ofMillis(500)) // 等待超时
.build();
RateLimiter rateLimiter = RateLimiter.of("myService", config);
// 装饰你的函数
Supplier<String> decorated = RateLimiter.decorateSupplier(rateLimiter, () -> "result");
| 方案 | 推荐场景 | 是否内置 |
|---|---|---|
| Guava RateLimiter | 通用场景 ✅ 首选 | 第3方库 |
| Resilience4j | 微服务/异步场景 | 第3方库 |
| 自己实现 | 简单场景/学习 | 手动 |
| JDK并发工具 | 基础控制 | 组合实现 |
Java 标准库没有直接提供令牌桶 API,但 Guava 的 RateLimiter 是最常用、最成熟的替代方案。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播