<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">As an aside, that seems like a much more complicated and obscure design than using closable queues.<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jul 9, 2024, at 10:24 AM, Michal Domagala <<a href="mailto:outsider404@gmail.com" class="">outsider404@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Indeed, for 25+ years thread is GC root.<div class="">But for 3+ years virtual threads are present and they are documented as ephemeral.</div><div class="">Developers are used to alive threads and virtual, alive threads are not confusing. But virtual, alive threads documented as ephemeral are confusing.</div><div class="">Moreover, the idea that VT from Executors API is GCed but from Thread API not looks inconsistent. But it is low confusion. Working against documentation is high confusion.</div><div class=""><br class=""></div><div class="">Let's consider my case. I take 1000 Kafka events for concrete people each poll. 90% of events are ignored (not my customers), 10% are processed (my customers), but each event must be acked.</div><div class="">Each customer has a blocking queue. 10% is distributed to proper queues. Each queue has a VT, which processes the event and finally ack the event.</div><div class="">From time to time customers are off. Their blocking queues are thrown away. </div><div class="">There is a chance that at the same moment the customer is off, new poll come with customer events. Kafka listener put event to customer queue and expects VT will ack the event.</div><div class="">VT can't be stopped by the "customer-off" process, because new events may come to the blocking queue anytime.</div><div class=""><br class=""></div><div class="">Race can be solved without synchronization. GC "knows" when the blocking queue is not visible by Kafka listener thread and "stops" the VT by reclaiming its resources.<br class=""><br class="">I hope this example is clear enough to see that reclaiming VT resources by GC is simple and automatic when manual solution requires thread synchronization and is prone to errors.</div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="gmail_attr">wt., 9 lip 2024 o 16:24 Alan Bateman <<a href="mailto:Alan.Bateman@oracle.com" class="">Alan.Bateman@oracle.com</a>> napisaĆ(a):<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 09/07/2024 12:51, Michal Domagala wrote:<br class="">
> Thanks for valuable observability context<br class="">
><br class="">
> As I understand, initially VT created by Thread API was not observable <br class="">
> in thread dump and VT created by Executors API was observable. It was <br class="">
> confusing and now both kinds of VT are observable. Make sense.<br class="">
> But observability is reached by strong reference. VT created by Thread <br class="">
> API are strongly referenced until stop and not GC'ed until stop and VT <br class="">
> created by Executors API are not referenced at all and GC'ed when not <br class="">
> reachable, regardless of being stopped or not. That's not OK and much <br class="">
> worse than previous confusion.<br class="">
<br class="">
An ExecutorService implementation has to keep a reference to each <br class="">
task/thread because of the shutdownNow and close method. There are other <br class="">
thread groupings that arise when using structured concurrency that <br class="">
require a thread executing a main task wait for threads executing <br class="">
subtasks to finish executing.<br class="">
<br class="">
As things stand I don't expect there will be much confusion. For 25+ <br class="">
years, a started thread is alive (and strongly reachable) until it <br class="">
terminates. Having virtual thread work mostly the same shouldn't be a <br class="">
surprise. As I said, the door hasn't been closed on introducing some <br class="">
notion of ephemeral thread in the future. It's not really feasible right <br class="">
now because of finalization and because of several issues related to <br class="">
cleaner actions and explicit APIs to keep some object reachable until a <br class="">
thread gets to some point in its execution. So there is more to this <br class="">
than just observability (and yes of course observability could traverse <br class="">
other reference types if needed).<br class="">
<br class="">
As regards the thread counting in the root container when running with <br class="">
the undocumented system property jdk.trackAllThreads is set to false. <br class="">
That is the count of the live (started but not terminated) threads in <br class="">
that thread grouping. It is a left over from when we will mulling over <br class="">
what the right default should be (reporting a thread count when you <br class="">
can't list the threads has some value).<br class="">
<br class="">
-Alan<br class="">
</blockquote></div>
</div></blockquote></div><br class=""></body></html>