Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Control ExecutorService to execute N tasks per second maximum

How to control/limit the tasks that are submitted to a ExecutorService? I have SMSTask that sends SMS messages and I need to control the executor so that it can only send at maximum N messages/second.

like image 423
Eng.Fouad Avatar asked Nov 08 '12 14:11

Eng.Fouad


People also ask

Which are used to delegate tasks for execution to an ExecutorService?

There are a few different ways to delegate tasks for execution to an ExecutorService : execute(Runnable) submit(Runnable) submit(Callable)

What is ExecutorService multithreading?

The Java ExecutorService is a construct that allows you to pass a task to be executed by a thread asynchronously. The executor service creates and maintains a reusable pool of threads for executing submitted tasks.

Which method of ExecutorService is called to check that all tasks are complete following shutdown?

When using an Executor, we can shut it down by calling the shutdown() or shutdownNow() methods. Although, it won't wait until all threads stop executing. Waiting for existing threads to complete their execution can be achieved by using the awaitTermination() method.

What is ExecutorService and how its works?

ExecutorService is a JDK API that simplifies running tasks in asynchronous mode. Generally speaking, ExecutorService automatically provides a pool of threads and an API for assigning tasks to it.


2 Answers

Assuming you are creating one SMS message per task you can use a ScheduleExecutorService.

final Queue<Task> tasks = new ConcurrentLinkedQueue<Task>();
int ratePerSecond = 10;
final ExecutorService es = Executors.newCachedThreadPool();
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ses.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        final Task task = tasks.poll();
        if (task == null) return;
        es.submit(new Runnable() {
            @Override
            public void run() {
                process(task);
            }
        });
    }
}, 0, 1000/ratePerSecond, TimeUnit.MILLISECONDS);

Add tasks to the queue and they will be processed at a rate of 10 per second.

like image 107
Peter Lawrey Avatar answered Oct 14 '22 22:10

Peter Lawrey


Try RateLimiter from Guava. You must share one instance between all tasks running in the pool:

final RateLimiter rateLimiter = RateLimiter.create(N)

//and in your task:

rateLimiter.tryAcquire();
sendSms();

tryAcquire(); will block for the amount of time precisely to preserve N frequency.

See also:

  • RateLimiter - discovering Google Guava
like image 21
Tomasz Nurkiewicz Avatar answered Oct 14 '22 22:10

Tomasz Nurkiewicz