Điều này phụ thuộc vào ứng dụng.
Hãy tưởng tượng trường hợp trong đó nhiều chủ đề muốn có một dấu hiệu để làm một số hành động toàn cầu tốc độ-hạn chế với không burst cho phép (ví dụ bạn muốn giới hạn 10 hành động mỗi 10 giây nhưng bạn không muốn 10 hành động xảy ra trong giây đầu tiên và sau đó duy trì 9 giây dừng lại).
DelayedQueue có một nhược điểm: thứ tự mà chủ đề yêu cầu mã thông báo có thể không phải là thứ tự mà họ nhận được yêu cầu của họ. Nếu nhiều luồng bị chặn chờ mã thông báo, không rõ chuỗi nào sẽ lấy mã thông báo có sẵn tiếp theo. Bạn thậm chí có thể có các chủ đề chờ đợi mãi mãi, theo quan điểm của tôi.
Một giải pháp là có một khoảng thời gian tối thiểu giữa hai hành động liên tiếp và thực hiện các hành động theo cùng một thứ tự như chúng được yêu cầu.
Đây là một thực hiện:
public class LeakyBucket {
protected float maxRate;
protected long minTime;
//holds time of last action (past or future!)
protected long lastSchedAction = System.currentTimeMillis();
public LeakyBucket(float maxRate) throws Exception {
if(maxRate <= 0.0f) {
throw new Exception("Invalid rate");
}
this.maxRate = maxRate;
this.minTime = (long)(1000.0f / maxRate);
}
public void consume() throws InterruptedException {
long curTime = System.currentTimeMillis();
long timeLeft;
//calculate when can we do the action
synchronized(this) {
timeLeft = lastSchedAction + minTime - curTime;
if(timeLeft > 0) {
lastSchedAction += minTime;
}
else {
lastSchedAction = curTime;
}
}
//If needed, wait for our time
if(timeLeft <= 0) {
return;
}
else {
Thread.sleep(timeLeft);
}
}
}