Ini tergantung pada aplikasinya.
Bayangkan kasus di mana beberapa thread ingin token untuk melakukan beberapa tindakan global tingkat-terbatas dengan tidak meledak diperbolehkan (yaitu Anda ingin membatasi 10 tindakan per 10 detik, tetapi Anda tidak ingin 10 tindakan terjadi di kedua pertama dan kemudian tetap 9 detik berhenti).
DelayedQueue memiliki kelemahan: urutan thread yang meminta token mungkin bukan urutan pemenuhan permintaannya. Jika beberapa utas diblokir menunggu token, tidak jelas mana yang akan mengambil token yang tersedia berikutnya. Anda bahkan bisa memiliki utas menunggu selamanya, menurut saya.
Salah satu solusinya adalah memiliki interval waktu minimum antara dua tindakan berurutan , dan mengambil tindakan dalam urutan yang sama seperti yang diminta.
Berikut implementasinya:
public class LeakyBucket {
protected float maxRate;
protected long minTime;
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;
synchronized(this) {
timeLeft = lastSchedAction + minTime - curTime;
if(timeLeft > 0) {
lastSchedAction += minTime;
}
else {
lastSchedAction = curTime;
}
}
if(timeLeft <= 0) {
return;
}
else {
Thread.sleep(timeLeft);
}
}
}