Structured concurrency in JDK 21 is not only a powerful and flexible library feature, but one that is built deep into the runtime in a way that allows observability into the relationships among threads: https://openjdk.org/jeps/453
It's somewhat unfortunate that structured concurrency ended up being a preview feature in 21. I agree that it's a great addition but man it'd be nice if it made the LTS.
As it stands, probably won't be heavily used until Java 25.
Organisations that care about new features need to reconsider their stance on using Preview features and even more importantly sticking to versions for which the sales org offers an LTS service. The whole concept of LTS is designed for companies that are so uninterested in new features (often because their software is no longer heavily maintained) that they're willing to pay money not to receive them. There are a lot of such projects around, and the fact that non-legacy projects choose old versions and an LTS service shows that the ecosystem still hasn't adapted to the new release model.
While I tend to agree, it's just a losing battle (in my experience). The issue is that shockingly few people in organizations actually care about language improvements. Further, because orgs prioritize spitting out new features above all else, selling maintenance work like updating the JVM is seen more as pure waste than actual benefit to the company.
The one argument I've been able to make to get an update is "This has fallen out of support and will no longer get security updates". That seems to be the only motivator for my company to do updates.
That seems like a bad faith interpretation. Upgrading has both costs and risks. Even upgrades within the same major version can break things. LTS is about paying for stability, not a lack of features.
Well, yes, but in the past the versions that now get a new integer number (feature releases) were mandatory for everyone and there was no LTS at all. There were some differences, but not as big as many think. The biggest one was the psychological aspect of the name (7u4 or 8u20, which were not patch releases but big feature releases).
So why did we create the LTS service? 1. Because the new feature releases, while no more risky than the old ones (like 7u4 and 8u20), do require a little more work that companies don't want to put into legacy applications, and 2. Many companies indeed are willing to pay for more stability for their legacy apps.
So while it is absolutely true that some projects want better stability, this level of stability is new. Companies that religiously stick to old versions now didn't do that in the past. The simplest explanation is that the new release model isn't yet understood, not that thousands of companies changed their risk strategy.
Congrats to you and the team on this huge milestone!
Really looking forward to taking advantage of these things (transparently and automatically!) in ZIO/Scala... which I think shows the true power of the JVM-as-platform approach you're taking!
You could always set the backing thread pools for core.async and agents in Clojure. That gives you the ability to use virtual threads right now.
But in order to avoid thread pinning, there will need to be some code changes to convert some uses of synchronized to ReentrantLock. How fast that happens will depend upon the given library maintainer. Here's an issue for making some of these changes in Clojure's core library: https://clojure.atlassian.net/browse/CLJ-2771
I've tested Clojure's agents with the new virtual threads for my targeted use case they're significantly faster than before - I can spin up tens of thousands of mostly idle agents and reach performance close enough to core.async for me.