#Is it recommended to use CompletableFuture.supplyAsync in web-apps?

1 messages · Page 1 of 1 (latest)

dreamy dome
#

I understand that this will spawn a new thread. Now let's say there are 4000 users calling the endpoing containing this async call. Will it slow down the server since it now has to handle more threads?

wary mapleBOT
#

<@&987246399047479336> please have a look, thanks.

wary mapleBOT
#

While you are waiting for getting help, here are some tips to improve your experience:

Code is much easier to read if posted with syntax highlighting and proper formatting.

If nobody is calling back, that usually means that your question was not well asked and hence nobody feels confident enough answering. Try to use your time to elaborate, provide details, context, more code, examples and maybe some screenshots. With enough info, someone knows the answer for sure.

Don't forget to close your thread using the command </help-thread close:1027500463647621170> when your question has been answered, thanks.

grizzled nest
#

who said that it will spawn a new thread with each call?

#

it uses the background forkjoinpool

#

its max size is equal to number of CPU threads minus one

dusky sierra
#

Take a look at Spring WebFlux if you want to handle massive amounts of users asynchronous

tame prism
#

flux is just the same under the hood

#

futures work just fine

#

u can spawn millions of tasks with it and it works perfectly fine

#

ive done it myself, processing 1million files and uploading them in just a few minutes

#

10x as fast as our actual c++ code

#

once we have virtual/green threads (very soon), it will be even better

calm spade
#

Java has a thread pool called fork join pool

#

And stuff like streams/futures/etc pull threads from the pool and use them

#

It is very efficient

stone forge
#

Don't use the fork join pool for a web server. The number matches your number of CPU cores, which is usually about 8 or so. If you have dozens or even hundreds of concurrent users all contending for that small threadpool then your system will come to a crawl.

The same is true for parallel streams - don't use them on a web server.

dreamy dome
# grizzled nest who said that it will spawn a new thread with each call?

I have seen examples where an ExecutorService is created and they submit the future to it like in here

ExecutorService threadpool = Executors.newCachedThreadPool();
Future<Long> futureTask = threadpool.submit(() -> factorial(number));

while (!futureTask.isDone()) {
    System.out.println("FutureTask is not finished yet..."); 
} 
long result = futureTask.get(); 

threadpool.shutdown();
dreamy dome
grizzled nest
grizzled nest
#

there are different types of executors out there

stone forge
#

Hmm, not sure what you mean. If you have 200 request threads for tomcat but they all fight for the 8 threads in your fork join then that 200 thread pool effectively turns into 8.

dreamy dome
#

I think we will just benchmark it when needed and use it. It seems safe anyway

stone forge
#

Although, I am wrong in my last message. Forkjoin pool will use the current thread plus <number of cores> threads. So it won't block those 200 threads but you will lose parellelism on a lot of your requests.

Also, even in a 1 user application, a forkjoin pool is intended for CPU bound tasks. If you're performing IO bound tasks then you also want to avoid a forkjoin pool too.

dreamy dome
#

Are there tips on how we should use the concurrency tools?

tame prism
grizzled nest
#

I don't see how avoiding executorservices on IO tasks is beneficial

stone forge
stone forge
grizzled nest
#

Forkjoinpool is an executorservice 🤷‍♂️

tame prism
#

u can specify what pool u want to create with executors though

grizzled nest
#

The main difference is that it can accept forkjointasks

tame prism
#

like Executors.newCachedThreadPool(64) for example

grizzled nest
#

Yeah and newWorkStealingPool is also there iirc

#

Which is your forkjoinpool

#

For IO bound tasks it doesn't really matter which type of executorservice you use, unless we're talking about Java 19 and virtual threads

#

I forgot, is OS scheduler smart enough to park threads which are IO blocked?

twin lynx
#

That's not the os task

dreamy dome
#

I forgot, but is there an await equivalent for CompletableFutures? Or do we just loop while the future is not done with !while(future.isDone())?

grizzled nest
#

use one of the .then...() methods

dreamy dome
#

May I know what that means? In JS we can do something like:

async function myCall() {
  const result = await myAsyncCall();
  return result;
}
``` Is there an equivalent in java?
wary mapleBOT
dreamy dome
#

So it doesn't block the thread

grizzled nest
#

when you call ComplatableFuture.supplyAsync(foo), you tell it to to execute foo in a background thread
if you do ComplatableFuture.supplyAsync(foo).thenAcceptAsync(acceptor), you tell it to also perform acceptor with the result of executing foo as the argument once that stage is completed

tame prism
#

its the same as async/await

#

a future/promise mechanism

#

just a different style of writing it

#

its more explicit

grizzled nest
#

@tame prism btw what happens if I follow an asynchronous stage with a synchronous one? does it block immediately?

tame prism
#

what do u mean?

grizzled nest
#

if in the example above you replace thenAcceptAsync with thenAccept

tame prism
#

its still async

#

it will just continue to use this particular thread

#

like, when u start CompletableFuture.supplyAsync(...), it will pick a thread from the pool for this task

#

if u now continue with .thenAccept(...) it will continue to use this thread for that chain

#

so the whole chain ends up in that thread

#

usually thats what u want, so thats the default

grizzled nest
#

and if you use thenAcceptAsync it can pick another thread?

tame prism
#

with thenAcceptAsync, u split the chain at that point and make it possible that it moves to a different thread

#

often thats not what u want

#

but it also doesnt matter too much

#

the really important part is being able to post task-chains on threads. whether the chain itself can be split further doesnt really matter too much

dreamy dome
#

Nevermind, I think it is possible

grizzled nest
#

hibernate is managed by a different connection pool

calm spade
tame prism
#

huh?

#

its always async

calm spade
#

oh right

#

so it will always try to get a new thread then

#

the thenAcceptAsync

tame prism
#

i dont quite follow

#

any future u create will be in some thread pool

#

quintegers question was about the difference when the then methods. i.e. when u want to follow up on the chain

#

like

CompletableFuture.supplyAsync(this::computeNumber)
  .thenAccept(System.out::println); // <- this one
#

vs

#
CompletableFuture.supplyAsync(this::computeNumber)
  .thenAcceptAsync(System.out::println); // <- this one
#

the difference is whether the print will be executed in the thread that computed the number or whether the chain is split here and we have 2 tasks instead of one task-chain

#

but the main motivation for using futures is to get the chain out of ur current thread. and both accomplish that just fine

#

latter variants mainly exist if u need very fine control over which threads exactly do something, since u can provide the executor

#

so in theory u could write

#
CompletableFuture.supplyAsync(this::readFile, filePool)
  .thenSupplyAsync(this::process, processPool)
  .thenAcceptAsync(this::upload, uploadPool)
#

in practice however, u cant really imagine situations in which u would actually need or want that

#

usually u just create a single chain and call it a day

wary mapleBOT
#

Closed the thread due to inactivity.

If your question was not resolved yet, feel free to just post a message to reopen it, or create a new thread. But try to improve the quality of your question to make it easier to help you 👍

dreamy dome
#

Does anyone have any idea if there is a library for futures that works with java 7? CompletableFuture seems to be a java 8 addition

dreamy dome
twin lynx
dreamy dome
#

I am not sure if we can, I still have to ask (but it will probably be JDK 8 or 11 if it happens). I noticed in previous jobs that companies tend to use older tech so It's probably unlikely

tame prism
#

for java though, usually people are very open to upgrading

#

since its fully backwards compatible

#

java 7 is kinda dangerous since it doesnt receive any security updates/patches anymore

#

so its fairly easy for an attacker/hacker to breach into

wary mapleBOT
#

Closed the thread due to inactivity.

If your question was not resolved yet, feel free to just post a message to reopen it, or create a new thread. But try to improve the quality of your question to make it easier to help you 👍

dreamy dome
#

Hello does anyone know what would be a good thread pool size?

ExecutorService executor = Executors.newFixedThreadPool(10);
``` Asking since we may create a spring bean ExecutorService to be used for running Runnables/Callables
tame prism
#

Executors.newCachedThreadPool()

dreamy dome
dreamy dome
#

I have another question if it's okay, Is it better to use parallel streams or a forkjointask?

dreamy dome
#

Does this mean they do the same thing?

tame prism
#

just bc they use the same pool, doesnt mean they work the same way, no

#

for example if u do valueStream.parallel().sum(), this will be computed in parallel chunks

#

with a spliterator

#

each spliterator part will be executed on the pool and then joined

dreamy dome
#

ah i see; I was looking for a parallel for each and it seems we have to do it this way https://stackoverflow.com/a/27558698

tame prism
#

it depends on the spliterator characteristics

#

how it behaves in practice

#

its not a "one future per iteration"