4

I am looking for a good solution or probably an API to solve the following problem:

  • My application does a task in a loop, for example it sends e-mails etc. I need to limit the average rate of messages to for example 100 messages per second or 1000 messages per last minute ...

No I am looking for an algorithm or an API which does exactly this task.

GargantuChet
  • 5,691
  • 1
  • 30
  • 41
Literadix
  • 1,379
  • 1
  • 18
  • 31

4 Answers4

4

You can use a ScheduledExecutorService to schedule tasks for a given period of time.

For example, to schedule 100 tasks per second you can say:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(nThreads);
scheduler.scheduleAtFixedRate(mailSender, 0, 10, TimeUnit.MILLISECONDS);

Obviously, you need to track how many tasks have executed and turn off the scheduler after the job is done.

dm3
  • 2,038
  • 2
  • 17
  • 20
  • Or have the scheduled task not do anything when there is nothing left to do. This avoids having to cancel and add it repeatedly. – Peter Lawrey Sep 08 '11 at 15:00
4

Token bucket algorithm is very easy to implement and use yet very powerful. You can control the throughput at runtime and queue some requests to handle peeks.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
3

Guava has a RateLimiter class that does exactly that.

Shailendra
  • 8,874
  • 2
  • 28
  • 37
mR_fr0g
  • 8,462
  • 7
  • 39
  • 54
3

The simplest way I can think of is to delay when to send each emails depending on how many are waiting.

final ScheduledThreadPoolExecutor service = new ScheduledThreadPoolExecutor(1);
int ratePerSecond = ...

public static void execute(Runnable run) {
   int delay = 1000 * service.getQueue().size() / ratePerSecond;
   service.schedule(run, delay, TimeUnit.MILLISECONDS);
}

This will ensure that the tasks are performed only as close to together as the rate allows.

Paulo Fidalgo
  • 21,709
  • 7
  • 99
  • 115
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130