Java节流机制 [英] Java thottling mechanism

查看:290
本文介绍了Java节流机制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:我使用的是Java 1.6.34,没有升级到Java 7的机会.

Update: I'm on Java 1.6.34 with no chance of upgrading to Java 7.

在一种情况下,我只能每分钟调用80次方法.它实际上是由第三方编写的服务API,如果您多次调用它,它将关闭"(忽略调用)其API:

I have a scenario where I am only allowed to call a method 80 times per minute. It's actually a service API written by a 3rd party, and it "shuts down" (ignores calls) its API if you call it too many times:

public class WidgetService {
    // Can only call this method 80x/min, otherwise it
    // it just doesn't do anything
    public void doSomething(Fizz fizz);
}

我想编写一个具有boolean canRun()方法的ApiThrottler类,该类将告诉我的Java客户端是否可以调用doSomething(Fizz)方法. (当然,它总是可以被称为 ,但是如果我们超出了我们的速率,就没有调用它的感觉.)

I'd like to write an ApiThrottler class that has a boolean canRun() method that will tell my Java client whether the doSomething(Fizz) method can be called or not. (Of course it can always be called, but there's no sense of calling it if we've exceeded our rate.)

这样可以让我编写如下代码:

So something that would allow me to write code like so:

// 80x/min
ApiThrottler throttler = new ApiThrottler(80);

WidgetService widgetService = new DefaultWidgetService();

// Massive list of Fizzes
List<Fizz> fizzes = getFizzes();

for(Fizz fizz : fizzes)
    if(throttler.canRun())
        widgetService.doSomething(fizz);

这不一定是API(ApiThrottler#canRun),但是我需要一个可靠的机制来暂停/睡眠,直到可以调用WidgetService#doSomething(Fizz) .

This doesn't necessarily have to be the API (ApiThrottler#canRun), but nevertheless I need a solid/reliable mechanism that will pause/sleep until WidgetService#doSomething(Fizz) can be called.

这让我感觉,就像我们进入使用多个线程的领域一样,这让我感觉,就像我们可以使用某种锁定机制和Java通知(wait()/notify())模型.但是由于没有这个领域的经验,我似乎无法将自己的头围在最优雅的解决方案上.预先感谢.

This makes me feel like we're heading into the realm of using multiple threads, which makes me feel like we could use some sort of locking mechanism and the Java notification (wait()/notify()) model. But having no experience in this realm, I can't seem to wrap my head around the most elegant solution. Thanks in advance.

推荐答案

最好的选择之一是使用信号量 http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html . 调用程序线程通过在信号量上调用acquire()每次执行对服务的调用时都会消耗许可,如果所有许可已被耗尽,该线程将阻塞.

Probably one of the best of options would be to use Semaphore http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html class and give it 80 permits every minute. This can be accomplished for example by using timer class http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html. The caller thread will consume permits every time it performs the call to the service by calling acquire() on the semaphore, which will block if all permits have been drained already.

正如您提到的,当然可以使用wait/notify和带有计时器或单独线程的整数计数器对此进行编码,但是与使用更现代的java.util.concurrent API相比,这将更加复杂我已经在上面概述了.

It would of course be possible to code this up using wait/notify and integer counter with timer or separate thread, as you mention, but that would be more complex compared to the usage of more modern java.util.concurrent API that I have outlined above.

它看起来可能接近以下内容:

It can look close to the following:

class Throttler implements TimerTask {
  final Semaphore s = new Semaphore(80);  
  final Timer timer = new Timer(true);

  Throttler() {
    timer.schedule(this, 0, 60*1000);   //schedule this for 1 min execution  
  }

  run() {  //called by timer 
    s.release(80 - s.availablePermits());
  }

  makeCall() {
    s.acquire();
    doMakeCall();
  }

}

这应该从Java 5开始起作用.

This should work starting from Java 5.

更好的解决方案是使用Guava的com.google.common.util.concurrent.RateLimiter.看起来可能像这样:

Also even nicer solution would be to use com.google.common.util.concurrent.RateLimiter from Guava. It can look like this:

class Throttler {
  final RateLimiter rateLimiter = RateLimiter.create(80.0/60.0);

  makeCall() {
    rateLimiter.acquire();
    doMakeCall();
  }
}

语义与信号量解决方案稍有不同,RateLimiter最有可能适合您的情况.

Semantics is slightly different compared to Semaphore solution, with RateLimiter being most probably better fit in your situation.

这篇关于Java节流机制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆