Live data from Hacker News

Java 21: The Nice, the Meh, and the Momentous

horstmann.com

71–80 of 191 posts

Re: Java 21: The Nice, the Meh, and the Momentous

#71
post #20

Earlier quoted context omitted.

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

Do you know if clojure will be adopting these virtual threads, or still using the macro-based approach?

[deleted]

Re: Java 21: The Nice, the Meh, and the Momentous

#72
Can anyone explain this comment: "In the past, a thread pool didn't just throttle the incoming requests but also the concurrent resources that your app consumed. If you now accept many more incoming requests, you may need other ways to manage resource consumption."

Re: Java 21: The Nice, the Meh, and the Momentous

#73

Earlier quoted context omitted.

That's all sequential code, it would be run inside a single "virtual thread". Note that the async code on the right is also sequential, just structured through an async API.

From my perspective they're not entirely equivalent. The async variant seems to be batching getImages and saveImages, while the sync variant gets and saves each image individually, sequentially.

They aren't perfectly equivalent because the virtual thread example uses a loop instead of the following (dropping the try/catch):

  // client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
  var response = client.send(request, HttpResponse.BodyHandlers.ofString()); 
  // .thenApply(HttpResponse::body)
  var body = response.body();
  // .thenApply(this::getImageURLs)
  var urls = getImageURLs(body);
  //  .thenCompose(this::getImages)
  var images = getImages(urls);
  // .thenAccept(this::saveImages)
  saveImages(images);
And if it had been written this way it would have been clearer that they are, in fact, equivalent. But generally people don't write like this, they use looping constructs.

Regardless, the important bit is that the parallel/concurrent bit of the async one is that it is cast off into an async system. The following execution steps are, well, steps. Each executed in sequence. Just like the body of the virtual thread example would be executed, but without the cumbersome noise of thenApply and thenCompose and such.

Re: Java 21: The Nice, the Meh, and the Momentous

#76

(1) It's a bit of a bad smell (which he points out) that records aren't being used much at all in the Java stdlib, I wrote something that built out stubs for the 17 and 18 stdlibs and that stood out like a sore thumb. I do like using records though. (2) I've looked at other ways to extend the collections API and related things, see https://github.com/paulhoule/pidove and I think the sequenced collections could have b…

I think virtual threads are huge.

The problem with regular threads is (a) multi-kb memory stack per thread and (b) consuming a file handle.

Either of those severely limits the scalability of the most "natural" parallelism constructs in Java (perhaps generally). Whole classes of application can now just be built "naturally" where previously there were whole libraries to support it (actors, rxJava, etc etc).

It make take a while for people to change their habits, but this could be quite pervasive in how it changes programming in general in all JVM languages.

Re: Java 21: The Nice, the Meh, and the Momentous

#77
post #38

Earlier quoted context omitted.

With the API being nearly the same, I keep just thinking that Virtual Threads are basically identical to Platform Threads except that they use far less memory (so you can have lots more of them). Are there any other actual differences? Better Peformance?

The relationship between throughput, latency, and concurrency in servers is expressed via Little's theorem. If your server is written in the thread-per-request style -- the only style for which the platform offers built-in language, VM, and tooling support -- then the most important factor affecting maximum throughput is the number of threads you can have (until, of course, the hardware is fully utilised). Being able…

I watched the video and thoroughly enjoyed it, thank you for sharing it! I have a question that is perhaps not entirely related to the video, but it touches the topic of context switches. I've read this post [1] by Chris Hegarty, which explains that when calling the traditionally blocking network I/O APIs in the Java stdlib from a virtual thread, it uses asynchronous/poll-based kernel syscalls (IOCP, kqueue, epoll on Windows, Mac and Linux respectively) which I assume is to avoid blocking the carrier threads. That post was written in 2021, does it still hold true today in Java 21?

Reading that, it also makes me wonder what happens for disk I/O? Many other runtimes, both "green thread" ones like Golang and asynchronous like libuv/tokio, use a blocking thread pool (static or elastic) to offload these kernel syscalls to because, from what I've read, those syscalls are not easily made non-blocking like e.g epoll is. Does Java Virtual Threads do the same, or does disk I/O block the carrier threads? For curiosity, does Java file APIs use io_uring on Linux if it is available? It is a fairly recently added kernel API for achieving truly non-blocking I/O, including disk I/O. It doesn't seem to bring much over epoll in terms of performance, but has been a boon for disk I/O and in general can reduce context switches with the kernel by reducing the amount of syscalls needed.

[1]: https://inside.java/2021/05/10/networking-io-with-virtual-th...

Re: Java 21: The Nice, the Meh, and the Momentous

#78
post #60

Earlier quoted context omitted.

Virtual threads are strictly better than normal threads, no? I am thinking of any reason to still use traditional threads. Is there any downside?

Currently virtual threads aren't a good match if you have a CPU heavy workload. The scheduler isn't fair and if your code doesn't enter into any blocking code it won't be unmounted from the carrier thread.

Ahh. It makes sense. But it’s much better fit for file io/sockets/db.

Re: Java 21: The Nice, the Meh, and the Momentous

#79

Can anyone explain this comment: "In the past, a thread pool didn't just throttle the incoming requests but also the concurrent resources that your app consumed. If you now accept many more incoming requests, you may need other ways to manage resource consumption."

Yeah, if your server maxed out at 256 system threads you didn't have to worry about the fact that 1024 simultaneous calls would crash your DB. But now you're not limited by system threads

Re: Java 21: The Nice, the Meh, and the Momentous

#80
post #20
post #7

Virtual threads are going to be great, but they're still limited (still starved the pool when used with 'synchronized' blocks), and they aren't the structured concurrency power houses like kotlin coroutines, but its an invaluable tool that will only continue to accelerate as the ecosystem moves to adopt them. Expect a lot of libraries to start release versions that are java 21 baseline because of this feature alone.…

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

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!

Post reply on HN