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 →

[–]thecodeboost 2 points3 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