goosebump
goosebump

Reputation: 96

How to restrict the number of threads using a Java service

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.

Upvotes: 0

Views: 1136

Answers (3)

Peter Togara
Peter Togara

Reputation: 9

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();
    }
    }
    }

    }

Upvotes: 0

Randhir Ray
Randhir Ray

Reputation: 590

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();

}

Upvotes: 0

Vinay
Vinay

Reputation: 546

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);

Upvotes: 2

Related Questions