执行人服务和速率限制器



我有一个调用第三方API的类。现在我正在实施,一次只需要向第三方 API 发送 10 个请求。

我想过使用带有固定线程池的执行器服务,如下所示。

public class SimpleRateLimiter {
private ExecutorService executorService = Executors.newFixedThreadPool(10);
private static SimpleRateLimiter srl = new SimpleRateLimiter();
private SimpleRateLimiter() {}
public static SimpleRateLimiter getInstance() {
return srl;
}
public void doSomething() {
executorService.submit(new Runnable() {         
@Override
public void run() {
// call to 3rd party api
}
});
}
public void terminate() throws Exception {
executorService.shutdown();
}
}

我的理解是,由于我在池中只有 10 个工作线程,因此在任何时候都只能使用上述代码向第三方 API 发出 10 个请求。但这并不意味着执行程序服务将拒绝所有其他请求。相反,它将接受所有请求,并在完成它正在处理的任务执行后将请求分配给工作线程。

上述理解是否正确?

是的,您的理解是正确的,如果您查看Executors.newFixedThreadPool()的实现,它会返回一个具有无限BlockingQueue实现的ThreadPoolExecutor实例:

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

LinkedBlockingQueue是一个可选的有界BlockingQueue实现,如果您不提供任何队列最大大小Integer.MAX_VALUE,则可以忽略其构造函数的容量参数:

public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}

因此,关于您的问题,所有任务都将提交到线程池,一次只有 10 个线程将运行并调用 API,其余线程将排队。

相反,如果您使用具有有界BlockingQueue实现(如ArrayBlockingQueue)的自定义ThreadPoolExecutor而不是LinkedBlockingQueue在这种情况下,如果所有线程都繁忙且队列已满,并且您尝试提交另一个任务,则任务将被拒绝

在您的代码中,executorService.submit将继续接受新任务(直到Integer.MAX_VALUE任务),但在给定的时刻只会运行 10 个线程。

我想使用 [番石榴] (https://google.github.io/guava/releases/19.0/api/docs/index.html?com/google/common/util/concurrent/RateLimiter.html) 库来完成您的工作会更容易。

相关内容

  • 没有找到相关文章

最新更新