2

Consider the service class below:-

//Singleton service
public class InquiryService{

    private final ExecutorService es = Executors. newSingleThreadExecutor();
    private final CustomerService cs = new CustomerServiceImpl();

    public String process(){

          //Asynchronous calls to get info from CustomerService
          Future<String> result = es.submit(()->{return cs.getCustomer()});

          //Query database
          //Perform logic et all

          String customerName = result.submit.get();

          //continue processing.
    }
}

Service class above has an ExecutorService as field. If say, 100 concurrent requests on process method, does remaining (100-1) requests need to wait for thread availability?

How to solve the request wait? One option I could think is, instantiate, use and shutdown ExecutorService within process method. However aren't thread pool is meant to be reused?

Another option would be run as new Thread(new FutureTask<>(() -> {return cs.getCustomer()})) . Which one is correct way?

Updates:-

Based from comments and answers, the ExecutorService meant to be reused and frequent new Thread creation is expensive. Therefore another option is just run service call sequentially.

Awan Biru
  • 373
  • 2
  • 10
  • 3
    A thread pool of fixed size 1 is very limited in its use and yes, all other concurrent requests will have to wait for the thread (you could tweak that, but that's beside the point). Thread pools make much more sense when they are bigger than 1. – Joachim Sauer Sep 12 '19 at 10:18
  • There is already `newSingleThreadExecutor`. Creating a thread "pool" of 1 seems like a mistake – Michael Sep 12 '19 at 10:19
  • @Michael indeed, but that is the idea. – Awan Biru Sep 12 '19 at 10:21
  • @AwanBiru A mistake is the idea? Don't understand – Michael Sep 12 '19 at 10:25
  • @Michael no, the question is about concurrent access to a thread pool with single thread. But yes u are right I will update the sample above. – Awan Biru Sep 12 '19 at 10:29
  • 1
    @JoachimSauer, Re, "Thread pools make more sense when bigger than 1." That's a false generalization. There are valid use cases for thread pools with just one worker thread. So many, apparently, that the Java standard library provides a special method , `Executors.newSingleThreadExecutor()`, to simplify the creation of such. Just because a single-thread executor would not make sense in _this_ case, doesn't mean it wouldn't make sense in _any_ case. – Solomon Slow Sep 12 '19 at 14:02
  • @SolomonSlow: your interpretation of my statement is a false broadening of what I said ;-) Yes, 1-size thread pools have *some* uses, I never denied that. But pools with more than 1 size are way more common for good reasons. – Joachim Sauer Sep 12 '19 at 14:07
  • @JoachimSauer, Yes, saying that pools with size > 1 are way more common is a true statement. – Solomon Slow Sep 12 '19 at 14:10

1 Answers1

4

Your service is singleton which means only one instance exists throughout the runtime of your application (If implemented right!). So, effectively you have one ExecutorService handling a newFixedThreadPool(1).

does remaining (100-1) requests need to wait for thread availability?

Oh yes, all your 100-1 other requests has to wait since the first request is already executing in the thread present in the threadpool. Since the thread pool is of fixed size, it can never grow to handle other requests.

How to solve the request wait?

You need more threads in your threadpool to take up your task.

One option I could think is, instantiate, use and shutdown ExecutorService within process method

This is really a bad idea. The time taken to create and destroy Thread is too much. More on this here. That is whole idea of using a ThreadPool.

Another option would be run as new Thread(new FutureTask<>(() -> {return cs.getCustomer()}))

Constructing a new Thread(). Read my previous point.

So, what is right!?

One way would be to a Executors.newFixedThreadPool(10), so that (90-10) requests wait. Is it okay? Or maybe you are looking for newCachedThreadPool!

Warning: Also, please read about side-effects of using ThreadLocal in a ThreadPool, if applicable.

Mohamed Anees A
  • 4,119
  • 1
  • 22
  • 35
  • Yes the singleton implemented properly spring @Service or sort of. But why` new Thread()` is not preferable? Is that really expensive? – Awan Biru Sep 12 '19 at 10:36