0

My requirement is to restrict the number of threads which uses my service at any point in time. Executor service is not helping me here as my problem space is little different. Let me explain with an example.

I have exposed a REST API which does one job. On the fly, my controller invokes one of the services for the job execution. But I have to make sure only 'n' threads access the service. That means threads/API-access will be continuously growing but at some place, I have to keep them in waiting if 'n' threads are already using the service. And the end of the execution I should get the response from the service and returns back to the endpoint and then to the client.

If I use FutureTask and callable, how and where will I write the .get() method? Because my threads will be continuously growing in number and dynamic in nature.

Hope the problem statement is clear, let me know if more clarification required.

goosebump
  • 96
  • 1
  • 2
  • 13
  • You can use `ExecutorService`, just create a singleton thread pool of size `n`. Then for each request, you can submit and wait for the response. This way it will make you have only `n` threads accessing your service. – Sukhpal Singh Jul 27 '18 at 05:16
  • @SukhpalSingh How can I wait for the response if I am using the submit? Submit will return FutureTask right!. For retrieving the response from FutureTask object I need to call future.get(), but when I will call that is the question! :( – goosebump Jul 27 '18 at 05:56
  • Just call it then and there only. Every rest call is a new thread taken from the pool. – Sukhpal Singh Jul 27 '18 at 05:59
  • If I call then and there only, futuretask.get() might return null, because task will take some time to complete right? Correct me if I missing something. – goosebump Jul 27 '18 at 06:08
  • `get()` waits if necessary for the computation to complete, and then retrieves its result. – Sukhpal Singh Jul 27 '18 at 10:40

3 Answers3

2

If you just want to restrict the max number of threads which can access your service, then you might use Bounded Semaphore and can provide the max number of permits. Here is the sample code (assuming that your service is singleton) :-

public class SampleService {
    private Semaphore semaphore = new Semaphore(n, true);

    public void someMothod() {
        try {
            semaphore.acquire();

            // execute the task

        } catch (InterruptedException e) {
        } finally {
            semaphore.release();
        }

    }
}

You have to make sure that only one instance of semaphore is created. If you can have multiple instances of your service in the application, then make semaphore static.

private static Semaphore semaphore = new Semaphore(n, true);
Vinay
  • 526
  • 3
  • 6
0

You can use ExecutorCompletionService for this. Just create an ExecutorService with fixed no of threads as stated below

ExecutorService pool = Executors.newFixedThreadPool(5);

Now create an ExecutorCompletionService using this ExecutorService.

ExecutorCompletionService completionService = new ExecutorCompletionService(pool);

Then after submitting your task you can iterate and get the future and the job result from the future as well. This won't block the thread as being done when you use Future returned from just an ExecutorService.

for(int i = 0; i < worker size ; i++) {
    Future future = completionService.take();

     Object content = future.get();

}
Randhir Ray
  • 540
  • 5
  • 14
0
You can solve this by using both Semaphores and Future<T>. We have 2 types of Semaphores, i.e. Counting Semaphores and Binary Semaphores. If you want multiple threads to access your resource you, then use Counting semaphores.
Code example:

    public class RestrictApiCalls {
    private Sempaphore semaphore =  new Semaphore(3);
    private ExecutorService executor =  Executors.newFixedThreadPool(3);
    
     public void call(){
       try{
        semaphore.acquire();
        Future<String> future  =  executor.submit(()->{
         Thread.sleep(1000);
         return "Call successful";
        });
      try{
          String response  =  future.get();
        }catch(Exception e){
         //handle exception here
        }
     }catch(Exception e){
      // handle
    }
    finally{
     semaphore.release();
    }
    }
    }

    }