import com.google.common.util.concurrent.Monitor; import com.google.common.util.concurrent.RateLimiter; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; /** * @create 2021-02-15 19:21 * @desc 令牌环桶算法的使用案例 **/ public class RateLimiterTokenBucket { //当前活动的商品数量 private final static int MAX = 100; //订单编号 private int orderID; //单位时间内(每秒)只允许 10 个用户能够抢购到商品,也就是说“订单服务”将会被匀速地调用 private final RateLimiter rateLimiter = RateLimiter.create(10.0D); private Monitor bookOrderMonitor = new Monitor(); public void bookOrder(Consumer<Integer> consumer) throws NoProductionException,OrderFailException { // 如果当前商品有库存,则执行抢购操作 if( bookOrderMonitor.enterIf(new Monitor.Guard(bookOrderMonitor) { @Override public boolean isSatisfied() { return orderID < MAX; } })) { try { //抢购商品,最多等待 100 毫秒 if( !rateLimiter.tryAcquire(100, TimeUnit.MILLISECONDS)) { // 如果在 100 毫秒之内抢购仍然失败,则抛出订单失败的异常 throw new OrderFailException("book order failed, please try again later."); } orderID++; // 执行订单订购操作 consumer.accept(orderID); } finally { bookOrderMonitor.leave(); } } else { // 如果当前没有库存,则抛出没有商品的异常,该异常将不会再次进行尝试动作 throw new NoProductionException("No available production now."); } } }
-------------------------------------
/** * @create 2021-02-15 23:45 * @desc 自定义异常 **/ public class OrderFailException extends Exception { public OrderFailException(String message) { super(message); } }
------------------------------------------
/** * @create 2021-02-15 19:29 * @desc 自定义异常 **/ public class NoProductionException extends Exception { public NoProductionException(String message) { super(message); } }