#Is it recommended to use CompletableFuture.supplyAsync in web-apps?
1 messages · Page 1 of 1 (latest)
<@&987246399047479336> please have a look, thanks.
While you are waiting for getting help, here are some tips to improve your experience:
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.
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
Take a look at Spring WebFlux if you want to handle massive amounts of users asynchronous
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
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
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.
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();
@tame prism @stone forge I am not sure if we can use it. Is it safe or not? 😆
the number is your threads minus one for this very reason
this is an ExecutorService that by definition spawns new threads with each task
there are different types of executors out there
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.
I think we will just benchmark it when needed and use it. It seems safe anyway
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.
Are there tips on how we should use the concurrency tools?
btw, this amount can be changed via env var
I don't see how avoiding executorservices on IO tasks is beneficial
Ah yeah that's true
I would prefer an executorservice for IO tasks. I would avoid a forkjoin pool for IO tasks, since the forkjoin pool is intended for CPU bound tasks (although personally on a webserver I just use executorservice for both).
Forkjoinpool is an executorservice 🤷♂️
u can specify what pool u want to create with executors though
The main difference is that it can accept forkjointasks
like Executors.newCachedThreadPool(64) for example
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?
That's not the os task
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())?
What
No
Supply a callback
use one of the .then...() methods
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?
Detected code, here are some useful tools:
So it doesn't block the thread
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
its the same as async/await
a future/promise mechanism
just a different style of writing it
its more explicit
@tame prism btw what happens if I follow an asynchronous stage with a synchronous one? does it block immediately?
what do u mean?
if in the example above you replace thenAcceptAsync with thenAccept
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
and if you use thenAcceptAsync it can pick another thread?
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
I am looking at this library and would like to ask does this work with Hibernate?
Nevermind, I think it is possible
hibernate is managed by a different connection pool
if it was not async until now and now we need it async, can we make it so using that method then?
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
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 👍
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
why are you using java 7 ?
just upgrade ur java version
It's the version used to build the app 😆
can't you upgrade ?
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
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
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 👍
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
why using a fixed pool in the first place?
Executors.newCachedThreadPool()
Thanks! I thought there was only one type of thread pool
I have another question if it's okay, Is it better to use parallel streams or a forkjointask?
they both use the same pool
Does this mean they do the same thing?
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
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