Reputation: 3440
I have a class which invokes 3rd party API. Now I am working on implementation where at a time only 10 requests must be sent to the 3rd party api.
I have thought of using an executor service with a fixed thread pool as shown below.
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();
}
}
My understanding is that since I have only 10 worker threads in the pool so at any time only 10 requests can be made to 3rd party API using above code. But it doesn't mean that Executor service will reject all the other requests. Rather it will accept all the requests and assign the request to a worker thread once it has finished execution of the task it was working on.
Is the above understanding correct?
Upvotes: 4
Views: 2179
Reputation: 16908
Yes your understanding is correct, if you look at the implementation of Executors.newFixedThreadPool()
it returns an instance of ThreadPoolExecutor
with a unbounded BlockingQueue
implementation:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
The LinkedBlockingQueue
is an optionally bounded BlockingQueue
implementation where you can ignore the capacity argument of it's constructor, if you don't supply anything the max size of the queue is Integer.MAX_VALUE
:
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
So in regards to your question all the tasks will be submitted to the thread pool and at a time only 10 threads will run and make calls to the API and the rest will be queued.
In contrast if you use a custom ThreadPoolExecutor
with a bounded BlockingQueue
implementation like ArrayBlockingQueue
(with a predefined capacity) instead of a LinkedBlockingQueue
in that case if the all threads are busy and the queue is full and you try to submit another task the task will be rejected.
In your code the executorService.submit
will keep on accepting new tasks (till Integer.MAX_VALUE
tasks) but only 10 threads will run at a given moment in time.
Upvotes: 4
Reputation: 356
I guess it would be easier to use [guava] (https://google.github.io/guava/releases/19.0/api/docs/index.html?com/google/common/util/concurrent/RateLimiter.html) library to do your job.
Upvotes: 1