Virtual threads created more platform threads

Jianbin Chen jianbin at apache.org
Wed Jul 2 07:25:31 UTC 2025


Hi Alan,

Thank you for your detailed explanation, but I still have some questions.

I added these parameters to limit platform threads:
-Djava.util.concurrent.ForkJoinPool.common.parallelism=2
-Djdk.virtualThreadScheduler.parallelism=2
-Djdk.virtualThreadScheduler.maxPoolSize=2
-Djava.util.concurrent.ForkJoinPool.common.maximumSpares=2.

Initially, I only added `jdk.virtualThreadScheduler.maxPoolSize=2`, but I
found it had no effect. I then thought this parameter only limits the
number of platform threads for normal virtual threads and doesn't cover
cases with pinned threads. So I added the
java.util.concurrent.ForkJoinPool.common.maximumSpares parameter again, but
it still had no effect - the threads keep growing. My JDK version is
Temurin OpenJDK 21.0.7+6. I've also attached the jstack stack trace
information.

Best Regards.
Jianbin Chen, github-id: funky-eyes

Alan Bateman <alan.bateman at oracle.com> 于 2025年7月2日周三 14:31写道:

>
> On 02/07/2025 06:50, Jianbin Chen wrote:
> > :
> >
> > Thank you and everyone for your patient answers. I verified this with
> > JDK 24, and the same example did not show platform thread growth.
> > However, there's one thing I don't understand: why are these threads
> > never reclaimed? Most of them are in a waiting state - isn't this a
> > waste of resources? Sometimes it increases by hundreds of threads. Is
> > there any way to suppress this behavior on JDK 21?
>
> Just to confirm what was already said. The stack trace in the issue
> shows Netty DefaultPromise.await in Object.wait. Prior to JDK 24 this
> pinned the carrier thread. The implementation (prior to JDK 24) attempts
> to compensate for this by arranging for a spare platform thread (FJP
> worker) to be available. This seems to be what you are seeing. The
> number of threads won't grow to more than 256. The "Implementation Note"
> section of the Thread class description documents the system property to
> change this limit if necessary. It's very possible that setting it to a
> number will cause the system to hang/deadlock as no virtual thread can
> make progress if they are all blocked in Object.wait and waiting for
> another virtual thread to notify.
>
> As regards trimming. The idle workers will terminate once a keep alive
> time (30s, not configurable) is reached but only if the system is idle
> (at quiescent in FJP speak). In a busy system, or even a tiny load such
> as heart beat, then it may not happen. There were improvements in JDK 22
> [1] but it still requires that the system be idle for threads to terminate.
>
> -Alan
>
> [1] https://bugs.openjdk.org/browse/JDK-8319662
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250702/05bb41b5/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jstack(2).log
Type: application/octet-stream
Size: 30532 bytes
Desc: not available
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250702/05bb41b5/jstack2-0001.log>


More information about the loom-dev mailing list