16

CompletableFuture::supplyAsync(() -> IO bound queries)

How do I chose an Executor for CompletableFuture::supplyAsync to avoid polluting the ForkJoinPool.commonPool().

There are many options in Executors (newCachedThreadPool, newWorkStealingPool, newFixedThreadPool etc)

And I read about new ForkJoinPool here

How do I chose the right one for my use case ?

Community
  • 1
  • 1
premprakash
  • 1,505
  • 3
  • 18
  • 27
  • 1
    if the number of concurrent queries is going to be limited you can use a cached thread pool - if there's a chance that the number could be very high (several 100s or 1000s or more) you can use a fixed thread pool with a reasonable limit. The answer depends on your use case and parameters (memory, OS etc.). – assylias Oct 27 '15 at 20:07
  • 3
    Here is the best article I have ever read about Executors, from Jessica Kerr: http://blog.jessitron.com/2014/01/choosing-executorservice.html - You should read it. – Ruben Oct 27 '15 at 20:29
  • Nice article , thanks @Ruban. I am using AWS lambda as the compute engine and I have 1536MB of memory and I am not doing any recursive computation , so that eliminates ForkJoinPool. Based on that flow diagram, I guess CachedThreadPool is the most appropriate for my use case. – premprakash Oct 27 '15 at 21:26
  • 1
    See also http://stackoverflow.com/questions/949355/newcachedthreadpool-v-s-newfixedthreadpool and http://stackoverflow.com/questions/15058978/how-to-decide-whether-to-use-newcachedthreadpool-or-newfixedthreadpool – assylias Oct 27 '15 at 22:04
  • 1
    Just use the default one (common FJP). If you have problems with such approach, ask new question specifying exact problems you have. If you don't have problems, that's nice. – Tagir Valeev Oct 28 '15 at 08:01
  • Why not use the common pool? If you create executors you will just pollute the OS with threads. The only reason is if the task will sleep/busy wait. Is that what you mean by "IO bound queries"? The parallelism will be `(availableProcessors-1)` in most cases. So another option would be to set `java.util.concurrent.ForkJoinPool.common.parallelism` to a higher value. But that might slow down some uses of the common pool. – Claude Martin Nov 23 '15 at 07:34
  • 1
    Something else to consider is that you can not shut down the common pool. So if you ever might need that you should use your own `Executor`. – Claude Martin Nov 23 '15 at 07:35

2 Answers2

7

You should use public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) method. As executor you can use any from the Executors.new.. - it depends on your needs. It's better to use newFixedThreadPool() rather than newCachedThreadPool(), since newCachedThreadPool() can lead to performance issues creating to many threads or even throw OutOfMemoryError. Here's a very nice article with good examples.

Anton Antonenko
  • 121
  • 1
  • 4
0

Adding to Anton's Answer, it is wise to use newFixedThreadPool rather than newCachedThreadPool unless you know the operation will not cause OutOfMemoryError. Since, your request is an i/o process the usage of Async nio request such as AsynchronousFileChannel or Async Rest Client...etc could greatly supplement your performance.