令牌桶简单实现代码
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class TokenLimiter {
public static final String TOKEN = "lp";
private ArrayBlockingQueue blockingQueue;
private int limit;
private int period;
private int amount;
public TokenLimiter(int limit, int period, int amount) {
this.limit = limit;
this.period = period;
this.amount = amount;
blockingQueue = new ArrayBlockingQueue<>(limit);
init();
}
public void start(Object lock) {
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
synchronized (lock) {
addToken();
lock.notifyAll();
}
}, 500, this.period, TimeUnit.MILLISECONDS);
}
public boolean tryAcquire() {
// 队首元素出队
return blockingQueue.poll() != null;
}
private void init() {
for (int i = 0; i < limit; i++) {
blockingQueue.add(TOKEN);
}
}
private void addToken() {
for (int i = 0; i < this.amount; i++) {
// 溢出返回false
blockingQueue.offer(TOKEN);
}
}
}
测试代码:
public class TestTokenLimiter {
final static Object LOCK = new Object();
public static void main(String[] args) throws InterruptedException {
int period = 500;
TokenLimiter limiter = new TokenLimiter(2, period, 2);
limiter.start(LOCK);
// 让线程先产生2个令牌
synchronized (LOCK) {
LOCK.wait();
}
for (int i = 0; i < 4; i++) {
new Thread(() -> {
while (true) {
String name = Thread.currentThread().getName();
if (limiter.tryAcquire()) {
System.out.println(name + ":拿到令牌");
} else {
System.out.println(name + ":没有令牌");
}
try {
Thread.sleep(period);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
}



