RateLimiter

令牌桶算法

 

 

import java.util.concurrent.*;

public class MyRateLimiter {
    //令牌桶
    BlockingQueue<Integer>TOKEN_BUCKET=new LinkedBlockingDeque<>(5);

    public static void main(String[] args) {
        MyRateLimiter myRateLimiter=new MyRateLimiter();
        myRateLimiter.addTokenFixedRate();
       for(int i=0;i<10;i++){
                myRateLimiter.acqurie();
                System.out.println("第几次执行i:" + i + ",执行时间为:" + System.currentTimeMillis());
        }
    }
   /**
    * 定时添加令牌
    */
    public void addTokenFixedRate(){
        ScheduledExecutorService scheduledExecutorService= Executors.newSingleThreadScheduledExecutor();
        scheduledExecutorService.scheduleAtFixedRate(()->{
                    boolean suc=TOKEN_BUCKET.offer(1);
                    if(!suc){
                        System.out.println("令牌桶满了丢弃");
                    }
        },0,200,TimeUnit.MILLISECONDS);
    }

    public void acqurie(){
        while (TOKEN_BUCKET.poll()==null){};
    }

}

 

 

@CanIgnoreReturnValue
public double acquire(int permits) {
  long microsToWait = reserve(permits);
  stopwatch.sleepMicrosUninterruptibly(microsToWait);
  return 1.0 * microsToWait / SECONDS.toMicros(1L);
}
//Reserve 一路向下能查到如下代码  reserveEarliestAvailable

final long reserveEarliestAvailable(int requiredPermits, long nowMicros) {
    resync(nowMicros);
    long returnValue = nextFreeTicketMicros;
 // 现存令牌可以提供的令牌数
    double storedPermitsToSpend = min(requiredPermits, this.storedPermits);
 //需要刷新的令牌数
    double freshPermits = requiredPermits - storedPermitsToSpend;
 //等待时间=需要刷新的令牌数*固定间隔+存储许可等待时间
    long waitMicros =
        storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
            + (long) (freshPermits * stableIntervalMicros);
 //下次令牌生产时间=本次令牌生产时间+等待时间
    this.nextFreeTicketMicros = LongMath.saturatedAdd(nextFreeTicketMicros, waitMicros);
    this.storedPermits -= storedPermitsToSpend;
    return returnValue;
}
 
posted @ 2021-06-09 00:21  KLAPT  阅读(127)  评论(0编辑  收藏  举报