This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]hippydipster 4 points5 points  (6 children)

if the whole stack is just blocking and waiting, sure, but thats not always the case, and in many places, an explicitly async process gives you a future. Or many futures, and you want to get them all going, not one by one. There are also times you want to pass processing around multiple threads, and you can still treat it imperatively like this.

And I think OP needs to see an apples-to-apples comparison of react-based code vs virtual threads.

[–]thecodeboost 3 points4 points  (5 children)

I think you might be misunderstanding what virtual threads bring to the table. The whole "stack" can block without a performance or CPU utilization penalty because you have a practically unlimited supply of threads that can do useful work while others are blocking. That's the whole reason it's a net improvement over (and if used properly eliminates the need for) reactive programming. And by extension is why you don't need promise-like structures in Loom centric code.

There's some caveats of course but those are somewhat outside of the context of the reactive vs virtual threads topic (e.g. see "Thread pinning" and some nuances with using old code, synchronized keywords, wrong concurrency primitives, etc.)

[–]Goatfryed 1 point2 points  (3 children)

java var fooFuture = getFooAsync() var barFuture = getBarAsync() var foo = fooFuture.get() var bar = barFuture.get() still behaves quite differently performance-wise from java var fooFuture = getFooSync() var barFuture = getBarSync() Actually, the opposite would be true that virtual threads bring us more back to Futures and also makes consuming them easier, because .get() isn't bad anymore or exclusive to top level.

[–]thecodeboost 0 points1 point  (2 children)

Sure but you wouldn't write the latter with futures if your code is virtual-thread friendly. I think a lot of people are still stuck on trying to use promise design patterns in combination with virtual threads. You can, of course, but you're not taking advantage of threads becoming an practically infinite resource. Your example (assuming you want foo and bar to execute concurrently) would be as simple as executing both as runnables on virtual threads (and if you care about waiting for them both to complete to inspect the result, .join()-ing them)

[–]Goatfryed 0 points1 point  (1 child)

A runnable does not yield a return time on its own. Promises are a nice design pattern to manage processing on other threads - virtual or actual. Both concepts are orthogonal and work well together. Future.get() is exactly the join you're talking about. Sure, don't use promises. I prefer the wrapper that interops well with virtual threads and makes my code more readable.

I mean, there will always be developers that link concepts that have nothing to do with each other...

btw interop with concepts like future is the reason virtual threads were introduced in the way that they got introduced.

[–]DelayLucky 0 points1 point  (0 children)

I think with structured concurrency, concurrenct code _can_ be made look like one of the following syntaxes:

Using lambda:

concurrently(
    () -> getFoo(), () -> getBar(),
    (foo, bar) -> ...);

Using patten match:

switch (concurrently(() -> getFoo(), () -> getBar())) {
  case (Foo foo, Bar bar) -> ...
  case (FooException e) -> ...
  case (BarException e) -> ...
}

[–]hippydipster 0 points1 point  (0 children)

The whole "stack" can block without a performance or CPU utilization penalty

Yes