Search code examples
java-8completable-futureembedded-tomcat-8

Tomcat 8 with CompletableFutures in Java 8


I want to parallelise my application. I am using Tomcat8 to deploy my web application. I am using Tomcat Default settings(HTTP Connector Thread count 200 and Default JVM settings). I want to use CompletableFuture in Java to complete the task in parallel. Ex - If I have 3 tasks TASK1,TASK2,TASK3 then instead of executing them in sequence I want to execute each task in separate threads using CompletableFuture and combine results. My question is, at any point of time, Tomcat receives 200 request, How many Threads are safe to create in Executor? If Executors.newFixedThreadPool(600), is 600 is a good number because, at any point of time I get 200 request and three parallel task to complete so I need minimum 600 threads(Theoretically). I feel creating more Threads may loose performance.


Solution

  • How many threads you can create depends on many factors, mainly in the specifications of the machine and OS.

    This answer says.

    This depends on the CPU you're using, on the OS, on what other processes are doing, on what Java release you're using, and other factors. I've seen a Windows server have > 6500 Threads before bringing the machine down.

    I personally have used almost 1000 threads, and the performance of my machine was still good.

    About using Executors.newFixedThreadPool(600) you have to analize if that is the better executor type that fits your application caracteristics and needs.

    Here you can see a comparison between FixedThreadPool and CachedThreadPool:

    FixedThreadPool vs CachedThreadPool: the lesser of two evils

    If the constant thread pool (of 600), will have most of the threads idle most of the time, you can use the chache thread pool that will create as many threads as necessary and then will keep them for certain time or as long as they continue to being used. You would probably get a benefit of using fixed thread pool, if you have the 200 executing the 3 tasks constantly.

    You can also use the CachedThreadPool with a maximun number of threads to be createad using a custom thread factory.

    By the other hand, if most of the tasks are short tasks, you can use Executors.newWorkStealingPool() this ensures that your available cpu cores are always working, setting the level of parallelistm with Runtime.getRuntime().availableProcessors(), if some thread finishes its work, it can steal tasks from another threads queue.

    You can see more about ForkJoinPool and Executors.newWorkStealingPool() (note: newWorkStealingPool uses ForkJoinPool internally):

    Detailed difference between Java8 ForkJoinPool and Executors.newWorkStealingPool?