If I understand correctly, you have multiple endpoints and multiple users making requests concurrently.
Then you want to make sure that these requests happen at most at some rate, globally.
This is the basic idea:
You can add the requests you want to do to a queue. More precisely a ConcurrentLinkedQueue
of Runnable
(you will create custom runnables for each endpoint). Multiple threads can interact with this single queue concurrently.
Then you can use a Timer
to execute a command that takes one item from the queue and executes it. This way each interval a request is made, regardless of the rate at which they are added to the queue (unless it is empty, of course).
Replace Timer
with ScheduledThreadPoolExecutor
if needed.
You can improve upon this by stopping the Timer
(or stopping the ScheduledFuture
) if you are in a period of inactivity※. Plus, starting/scheduling it again when adding items to the queue (if it was stopped).
※: Keep track of the time of the last request. If you took something from the queue, update the time to the current time. If you did not, compare the time to the current time... if too much (for some definition of too much) time has passed, then you are in a period of inactivity.
I'm not sure how do you handle responses. However, independently of whatever or not they are synchronous. You have the option to pass a custom Consumer
where you can pass the result. In fact, your custom Runnable
(the one you add to the queue) could hold the Consumer
from the client.