In the code example for virtual threads, I have no idea what will happen in parallel.
How do I reason about the order in which the calls change the state of the world?
How do I reason about the order in which the calls change the state of the world?
// 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.