具有限制/吞吐量控制的Java Executor

mri*_*rip 27 java multithreading executors

我正在寻找一个Java Executor,它允许我指定限制/吞吐量/起搏限制,例如,不超过100个任务可以在一秒钟内处理 - 如果更多任务被提交,他们应该排队并稍后执行.这样做的主要目的是避免在遇到外部API或服务器时遇到限制.

我想知道基础Java(我怀疑,因为我检查过)或其他可靠的地方(例如Apache Commons)是否提供了这个,或者我是否必须自己编写.最好是轻量级的.我不介意自己写,但如果有一个"标准"版本在那里,我至少想先看看它.

Ort*_*ier 27

看看guavas RateLimiter:

速率限制器.从概念上讲,速率限制器以可配置的速率分配许可.如果需要,每个acquire()都会阻止,直到有许可证可用,然后接受它.获得后,不需要发放许可证.速率限制器通常用于限制访问某些物理或逻辑资源的速率.这与信号量形成对比,信号量限制并发访问的数量而不是速率(注意并发和速率密切相关,例如参见Little's定律).

它的线程安全,但仍然@Beta.无论如何,可能值得一试.

你必须将每次调用都Executor包含在速率限制器中.对于更干净的解决方案,您可以为其创建某种包装器ExecutorService.

来自javadoc:

 final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
  void submitTasks(List<Runnable> tasks, Executor executor) {
    for (Runnable task : tasks) {
      rateLimiter.acquire(); // may wait
      executor.execute(task);
    }
  }
Run Code Online (Sandbox Code Playgroud)


Two*_*The 6

Java Executor不提供这样的限制,仅限于线程数量,这不是您要寻找的.

一般来说,执行程序是限制此类操作的错误位置,它应该是在线程尝试调用外部服务器的时刻.例如,您可以通过在提交请求之前使用线程等待的限制信号量来执行此操作.

调用线程:

public void run() {
  // ...
  requestLimiter.acquire();
  connection.send();
  // ...
 }
Run Code Online (Sandbox Code Playgroud)

同时您定期(例如每60秒)安排一个(单个)辅助线程释放获取的资源:

 public void run() {
  // ...
  requestLimiter.drainPermits();  // make sure not more than max are released by draining the Semaphore empty
  requestLimiter.release(MAX_NUM_REQUESTS);
  // ...
 }
Run Code Online (Sandbox Code Playgroud)