Re[3]: Киллер фича JDK 21 - virtual threads
От: · Великобритания  
Дата: 09.05.23 22:01
Оценка:
Здравствуйте, m2user, Вы писали:

m> A>·>Виртуальные треды запускаются на пуле из ОС-тредов и на блокирующих операциях перешедулятся, стеки подменяются.

m> A>Получается автоматическая асинхроность без всякого переписывания кода. Умно, ждем в .NET такое.
m> Ну как не переписывать: нужно как минимум создать экземпляр VirtualThread и запихнуть туда лямбду с кодом
Лямбды тут непричём. Вообще.
wiring код немного поменяются. И собственно всё. Вся бизнес-логика остаётся как есть, и можно масштабировать старинный код, который все боятся трогать.

m>(а если ещё вспомнить, что лямбды в Java не умеют захватывать неконстантные переменные в отличие от C#)

Шо?! Они переменные со стека не умеют захватывать только. Как собственно и в шарпе.

m> Из статьи на которую ссылается TC, преимущество перед async/await неочевидно (там сравнение с async/await в Котлине)

m> (https://blog.rockthejvm.com/ultimate-guide-to-java-virtual-threads/)
С тем, что код тупой, обычный, синхронный, понятный любому индусу, без всякого мусора async/await, возможно написанный ещё до создания самого c#. Гугли "function coloring".
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: Киллер фича JDK 21 - virtual threads
От: m2user  
Дата: 09.05.23 23:25
Оценка: 21 (1)
m>> Погодите, а как же cancellation?
·>Банальный interrupt() например, доступный ещё с java 1.0.
·>Ну или Future.cancel() или любой другой паттерн.

И как это применимо к классическим локам без переписывания кода?
Если мне нужно отменить ожидание на lock, то придется его в VirtualThread обернуть?

Дополнение:
Согласно документации
Thread.interrupt не действует на обычную synchronized секцию, и не на любой Lock

Further, the ability to interrupt the ongoing acquisition of a lock may not be available in a given Lock class

Кроме того, согласно https://openjdk.org/jeps/444

There are two scenarios in which a virtual thread cannot be unmounted during blocking operations because it is pinned to its carrier:

When it executes code inside a synchronized block or method, or
When it executes a native method or a foreign function.


В JEP предлагают заменить synchronized block на ReentrantLock, т.е. придется править код.


·>Просто представь себе как бы ты писал простой, читабельный код, если ты знаешь, что там будет максимум десяток тредов. И представь себе, что этот код потом можно отмасштабировать на миллионы.


m>> Вот в C# например я не могу использовать обычную lock секцию с async/await и вместо этого вынужден делать крит. секцию на основе SemaphoreSlim, где есть асинхронный wait и Cancellation.

·>Именно. Вот об этом гне и говорю. Есть Wait, и ещё нужен AsyncWait и ещё с CancellationToken . Итого намножилось аж 12 методов. И это приходится размазывать повсюду.

Так и VirtualThread тоже самое.
Вместо await Task будет VirtualThread.join

Как в примере, из статьи на которую ты ссылался
@SneakyThrows
static void concurrentMorningRoutine() {
  var bathTime = bathTime();
  var boilingWater = boilingWater();
  bathTime.join();
  boilingWater.join();
}
Отредактировано 10.05.2023 0:44 m2user . Предыдущая версия .
Re[4]: Киллер фича JDK 21 - virtual threads
От: m2user  
Дата: 09.05.23 23:28
Оценка:
·>Лямбды тут непричём. Вообще.
·>wiring код немного поменяются. И собственно всё. Вся бизнес-логика остаётся как есть, и можно масштабировать старинный код, который все боятся трогать.

Можно и без лямбд, но Runnable/Callable при создании VirtualThread передать придется.

m>>(а если ещё вспомнить, что лямбды в Java не умеют захватывать неконстантные переменные в отличие от C#)

·>Шо?! Они переменные со стека не умеют захватывать только. Как собственно и в шарпе.

Разницу C# и Java применительно к захвату переменных лямбдами обсуждали тут: Класс для возврата значения из лямбды
Мне для получения результата Callable, обернутого в VirtualThread, придется к таким же ухищрениям прибегать, как в той теме?

m>> Из статьи на которую ссылается TC, преимущество перед async/await неочевидно (там сравнение с async/await в Котлине)

m>> (https://blog.rockthejvm.com/ultimate-guide-to-java-virtual-threads/)
·>С тем, что код тупой, обычный, синхронный, понятный любому индусу, без всякого мусора async/await, возможно написанный ещё до создания самого c#. Гугли "function coloring".

Ты утверждал, что код остается "плоским", однако из примеров в статье видно, что вложенность увеличивается

static Thread bathTime() {
  return virtualThread(
    "Bath time",
    () -> {
      log("I'm going to take a bath");
      sleep(Duration.ofMillis(500L));
      log("I'm done with the bath");
    });
}


И что насчет перехвата исключений? Перехватывать нужно внутри VirtualThread?
Re[5]: Киллер фича JDK 21 - virtual threads
От: m2user  
Дата: 10.05.23 00:30
Оценка: 7 (1)
M>Мне для получения результата Callable, обернутого в VirtualThread, придется к таким же ухищрениям прибегать, как в той теме?

M>И что насчет перехвата исключений? Перехватывать нужно внутри VirtualThread?


Посмотрел https://openjdk.org/jeps/444
Там есть поясняющий пример:
void handle(Request request, Response response) {
    var url1 = ...
    var url2 = ...
 
    try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
        var future1 = executor.submit(() -> fetchURL(url1));
        var future2 = executor.submit(() -> fetchURL(url2));
        response.send(future1.get() + future2.get());
    } catch (ExecutionException | InterruptedException e) {
        response.fail(e);
    }
}
 
String fetchURL(URL url) throws IOException {
    try (var in = url.openStream()) {
        return new String(in.readAllBytes(), StandardCharsets.UTF_8);
    }
}


По-видимому Executors.newVirtualThreadPerTaskExecutor — предполагаемое решение для обоих случаев.
Но разворачивать ExecutionException до IOException придется вручную
Re[5]: Киллер фича JDK 21 - virtual threads
От: · Великобритания  
Дата: 10.05.23 09:17
Оценка:
Здравствуйте, m2user, Вы писали:

M>·>Лямбды тут непричём. Вообще.

M>·>wiring код немного поменяются. И собственно всё. Вся бизнес-логика остаётся как есть, и можно масштабировать старинный код, который все боятся трогать.
M>Можно и без лямбд, но Runnable/Callable при создании VirtualThread передать придется.
Не понял. Для реального треда тоже. И что?

m>>>(а если ещё вспомнить, что лямбды в Java не умеют захватывать неконстантные переменные в отличие от C#)

M>·>Шо?! Они переменные со стека не умеют захватывать только. Как собственно и в шарпе.
M>Разницу C# и Java применительно к захвату переменных лямбдами обсуждали тут: Класс для возврата значения из лямбды
Просто шарп компилятор создаёт класс, неявно делая переменную которая выглядит как на стеке полем класса. Грабля как из javascript.
Лично мне подход java нравится больше, т.к. никакой магии не делается, всё явно, никаких сюрпризов.

M>Мне для получения результата Callable, обернутого в VirtualThread, придется к таким же ухищрениям прибегать, как в той теме?

У callable есть возвращаемое значение.
Ты, видимо, что-то не так понял. Для запуска треда хоть реального, хоть виртуального, тебе надо как-то передать код который будет там работать. Это везде так, и в C# и даже в C. И к сабжу это никакого отношения не имеет.
Для более удобных способов обмена данными между тредами есть свой инструментарий, очень много разного.

И никакого публичного класса VirtualThread нет. С сабжем у тебя в коде будет всё тот же класс Thread из java 1.0. Меняется только способ создания экземпляра класса.

m>>> Из статьи на которую ссылается TC, преимущество перед async/await неочевидно (там сравнение с async/await в Котлине)

m>>> (https://blog.rockthejvm.com/ultimate-guide-to-java-virtual-threads/)
M>·>С тем, что код тупой, обычный, синхронный, понятный любому индусу, без всякого мусора async/await, возможно написанный ещё до создания самого c#. Гугли "function coloring".
M>Ты утверждал, что код остается "плоским", однако из примеров в статье видно, что вложенность увеличивается
Увеличивается по сравнению с чем?

M>И что насчет перехвата исключений? Перехватывать нужно внутри VirtualThread?

Ничего не меняется. Как работало с обычными Thread, так и будет.

Иными словами, весь существующий threading API у тебя сохраняется как есть. А сабж даёт тебе возможность запустить миллион тредов.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Киллер фича JDK 21 - virtual threads
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.05.23 10:47
Оценка:
Здравствуйте, m2user, Вы писали:

M>Так и VirtualThread тоже самое.

M>Вместо await Task будет VirtualThread.join

M>Как в примере, из статьи на которую ты ссылался

M>
M>@SneakyThrows
M>static void concurrentMorningRoutine() {
M>  var bathTime = bathTime();
M>  var boilingWater = boilingWater();
M>  bathTime.join();
M>  boilingWater.join();
M>}
M>


Лично мне больше нравится вариант джавы, а то все эти async/await как будто не лезут в голову молодому поколению девелоперов. Хотя, в целом, трудно сказать, насколько легко будет писать код для новой версии джавы. Наверняка там тоже будет много хитрых вещей "вызывайте вот это, если на двадцать уровней по стеку вверх не было вон того"
Re[4]: Киллер фича JDK 21 - virtual threads
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.05.23 10:50
Оценка:
Здравствуйте, ·, Вы писали:

·>wiring код немного поменяются. И собственно всё. Вся бизнес-логика остаётся как есть, и можно масштабировать старинный код, который все боятся трогать.


Старинный код скорее всего сделан последовательным и он будет скорее всего нереэнтерабельным, да с тред-локал. Соответсвенно уже на этом можно нарыть кучу граблей, если сделать такое многопоточным.
Re[6]: Киллер фича JDK 21 - virtual threads
От: · Великобритания  
Дата: 10.05.23 11:19
Оценка:
Здравствуйте, m2user, Вы писали:

M>>Мне для получения результата Callable, обернутого в VirtualThread, придется к таким же ухищрениям прибегать, как в той теме?

M>>И что насчет перехвата исключений? Перехватывать нужно внутри VirtualThread?
M>По-видимому Executors.newVirtualThreadPerTaskExecutor — предполагаемое решение для обоих случаев.
Это такой пример. Тут из треда который выполняет handle (которых уже может быть овердофига), запускается ещё два новых треда и ожидается их завершение.
Покажи аналогичный код лучше.

Это не предполагаемое решение (решение вообще чего??), а демонстрация того, что вместо того как принято сейчас — глобальный пул тредов, который запускается при старте приложения осторожно используется, теперь пул можно просто внутри любого метода на секундочку создать, забабахать туда кучку тредов и тут же выкинуть.

Заметь, там есть readAllBytes в двух тредах. Т.е. это вот так выглядит асинхронный IO с epoll теперь.

M>Но разворачивать ExecutionException до IOException придется вручную

Зачем? И почему _придётся_?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 10.05.2023 11:28 · . Предыдущая версия .
Re[5]: Киллер фича JDK 21 - virtual threads
От: · Великобритания  
Дата: 10.05.23 11:25
Оценка:
Здравствуйте, Pauel, Вы писали:

P>·>wiring код немного поменяются. И собственно всё. Вся бизнес-логика остаётся как есть, и можно масштабировать старинный код, который все боятся трогать.

P>Старинный код скорее всего сделан последовательным и он будет скорее всего нереэнтерабельным, да с тред-локал.
Дык тред-локал он и для виртуального треда локал!

P> Соответсвенно уже на этом можно нарыть кучу граблей, если сделать такое многопоточным.

Я имею в виду, что у тебя есть некий скажем http-сервер, в хендлерах которых у тебя последовательный код, который ходит в базу, в файлы, етс, и отдаёт результат — и всё последовательно. Сейчас такое можно намасштабировать на 200 одновременных соединений, по треду на каждое, начнёт разбухать память и т.п. С сабжем треды будут виртуальные и их можно дофига.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Киллер фича JDK 21 - virtual threads
От: · Великобритания  
Дата: 10.05.23 11:49
Оценка:
Здравствуйте, m2user, Вы писали:

M>·>Банальный interrupt() например, доступный ещё с java 1.0.

M>·>Ну или Future.cancel() или любой другой паттерн.
M>И как это применимо к классическим локам без переписывания кода?
M>Если мне нужно отменить ожидание на lock, то придется его в VirtualThread обернуть?
Непонятно что ты хочешь. Виртуальные треды не дают какой-то новый дополнительный контроль над локами. Они просто позволяют запускать больше тредов, чем ОС может себе позволить.
Если у тебя в коде не было возможности прервать какой-то лок, то она не появится магически. Просто пока миллион тредов висят на этом локе, ещё миллион тредов могут продолжать работать.

M>В JEP предлагают заменить synchronized block на ReentrantLock, т.е. придется править код.

Да, ложка дёгтя есть. Вроде обещают исправить: "In a future release we may be able to remove pinning inside synchronized".

m>>> Вот в C# например я не могу использовать обычную lock секцию с async/await и вместо этого вынужден делать крит. секцию на основе SemaphoreSlim, где есть асинхронный wait и Cancellation.

M>·>Именно. Вот об этом гне и говорю. Есть Wait, и ещё нужен AsyncWait и ещё с CancellationToken . Итого намножилось аж 12 методов. И это приходится размазывать повсюду.

M>Так и VirtualThread тоже самое.

M>Вместо await Task будет VirtualThread.join
Не совсем. Этот await не нужно протаскивать везде.
Т.е. у тебя есть какой-то обычный бизнес-код с синхронным readAllBytes — и у него никакого Task/async нет. И join нужен только собственно чтобы дождаться результата от всех тредов.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Киллер фича JDK 21 - virtual threads
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.05.23 12:27
Оценка:
Здравствуйте, ·, Вы писали:

·>Дык тред-локал он и для виртуального треда локал!


Особенность виртуальных тредов и важный бенефит — ничтожный футпринт по памяти. С тред локалами эта особенность исчезает.

·>Я имею в виду, что у тебя есть некий скажем http-сервер, в хендлерах которых у тебя последовательный код, который ходит в базу, в файлы, етс, и отдаёт результат — и всё последовательно. Сейчас такое можно намасштабировать на 200 одновременных соединений, по треду на каждое, начнёт разбухать память и т.п. С сабжем треды будут виртуальные и их можно дофига.


Если разрабы позаботились и жестко изолировались от фремворка http-сервера, то будет бенефит и можно масштабировать.
Но реально такой изоляцией судя по коду мало кто занимается.
На собесах любят поговорить про Clean Architecture, fremwork as a detail и тд, но вот в реальном мире таких применений ничтожное количество.
И это видно в тестах — на самом низком уровне люди пишут моки т.к. ктото где то в тредлокалах прокидывает чорт знает что.
Re[7]: Киллер фича JDK 21 - virtual threads
От: · Великобритания  
Дата: 10.05.23 12:41
Оценка: +1
Здравствуйте, Pauel, Вы писали:

P>·>Дык тред-локал он и для виртуального треда локал!

P>Особенность виртуальных тредов и важный бенефит — ничтожный футпринт по памяти. С тред локалами эта особенность исчезает.
А... ну да. Если тред-локал используется для протаскивания UserId, то ок.
А если кто-то решил, что тред-локал это хорошее место куда можно забабахать потокобезопасный кеш, а про ConcurrentHashMap ему не рассказали, "ведь тредов всё равно не может быть больше сотни", то да, не получится отмасштабировать as-is, придётся переписывать.

P>·>Я имею в виду, что у тебя есть некий скажем http-сервер, в хендлерах которых у тебя последовательный код, который ходит в базу, в файлы, етс, и отдаёт результат — и всё последовательно. Сейчас такое можно намасштабировать на 200 одновременных соединений, по треду на каждое, начнёт разбухать память и т.п. С сабжем треды будут виртуальные и их можно дофига.

P>Если разрабы позаботились и жестко изолировались от фремворка http-сервера, то будет бенефит и можно масштабировать.
P>Но реально такой изоляцией судя по коду мало кто занимается.
Servlet API это подразумевает.

P>На собесах любят поговорить про Clean Architecture, fremwork as a detail и тд, но вот в реальном мире таких применений ничтожное количество.

В ентерпрайзе, который сидит на 1.8 — дофига. (

P>И это видно в тестах — на самом низком уровне люди пишут моки т.к. ктото где то в тредлокалах прокидывает чорт знает что.

Ну по сути это глобальный Map<ThreadId, Object>. Вот что будет Object — уже от ситуации зависит...
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Киллер фича JDK 21 - virtual threads
От: m2user  
Дата: 10.05.23 14:27
Оценка:
·>Не понял. Для реального треда тоже. И что?

·>И никакого публичного класса VirtualThread нет. С сабжем у тебя в коде будет всё тот же класс Thread из java 1.0. Меняется только способ создания экземпляра класса.


M>>·>С тем, что код тупой, обычный, синхронный, понятный любому индусу, без всякого мусора async/await, возможно написанный ещё до создания самого c#. Гугли "function coloring".

M>>Ты утверждал, что код остается "плоским", однако из примеров в статье видно, что вложенность увеличивается
·>Увеличивается по сравнению с чем?

M>>И что насчет перехвата исключений? Перехватывать нужно внутри VirtualThread?

·>Ничего не меняется. Как работало с обычными Thread, так и будет.

·>Иными словами, весь существующий threading API у тебя сохраняется как есть. А сабж даёт тебе возможность запустить миллион тредов.


Да, я в курсе, что тип Thread остался старый.

Тут нужно определиться, к какому legacy коду ты собираешься применить virtualThread.
Если речь идет о http сервере (в этом твоем сообщении Киллер фича JDK 21 — virtual threads), в котором уже использются тяжеловесные треды (по одному на запрос), то конечно перевести его на легковесные вируальные треды (и получить экономию ресурсов) легко.
По сути нужно только заменить Lock на их interruptible версии.

Если же речь о коде, где нужно распараллелить операции, которые до этого выполнялись последовательно, то такой код понадобится раздробить на Runnable/Callable составляющие (функции или лямбды), попутно переписывая работу с переменными на стеке, возвратом результата, обработкой исключений.

Я утверждаю, что для такого кода:
1) по объему работы это не проще перевода на await/async
2) await/async позволил бы писать более "плоский" код (меньше вложенных блоков кода)

Executors.newVirtualThreadPerTaskExecutor, которыей я упомянул в соседнем сообщении, частично облегчает ситуацию — с возвратом результата Callable и пробросом исключения (в виде ExecutionException)
Re[7]: Киллер фича JDK 21 - virtual threads
От: m2user  
Дата: 10.05.23 14:36
Оценка:
M>>По-видимому Executors.newVirtualThreadPerTaskExecutor — предполагаемое решение для обоих случаев.
·>Это такой пример. Тут из треда который выполняет handle (которых уже может быть овердофига), запускается ещё два новых треда и ожидается их завершение.
·>Покажи аналогичный код лучше.

Async/await, как оно сделано в C#. Но конечно оно потребует и async версии readAllBytes.

M>>Но разворачивать ExecutionException до IOException придется вручную

·>Зачем? И почему _придётся_?

Для реализации нетривиальной логики обработки IOException — либо обрабатывать внутри fetchURL, либо разворачивать ExecutionException до IOException.
Re[7]: Киллер фича JDK 21 - virtual threads
От: m2user  
Дата: 10.05.23 14:48
Оценка:
m>>>> Вот в C# например я не могу использовать обычную lock секцию с async/await и вместо этого вынужден делать крит. секцию на основе SemaphoreSlim, где есть асинхронный wait и Cancellation.
M>>·>Именно. Вот об этом гне и говорю. Есть Wait, и ещё нужен AsyncWait и ещё с CancellationToken . Итого намножилось аж 12 методов. И это приходится размазывать повсюду.

M>>Так и VirtualThread тоже самое.

M>>Вместо await Task будет VirtualThread.join
·>Не совсем. Этот await не нужно протаскивать везде.
·>Т.е. у тебя есть какой-то обычный бизнес-код с синхронным readAllBytes — и у него никакого Task/async нет. И join нужен только собственно чтобы дождаться результата от всех тредов.

Это неполноценный асинхронный код, т.к. нет cancellation.
Если реализовать cancellation (как я понимаю, применительно к IO в Java это делается через AsynchronousChannel), то будут Future (вместо Task). И в итоге можно получить тот же function coloring
Re[7]: Киллер фича JDK 21 - virtual threads
От: · Великобритания  
Дата: 10.05.23 14:58
Оценка:
Здравствуйте, m2user, Вы писали:

M>Если же речь о коде, где нужно распараллелить операции, которые до этого выполнялись последовательно, то такой код понадобится раздробить на Runnable/Callable составляющие (функции или лямбды), попутно переписывая работу с переменными на стеке, возвратом результата, обработкой исключений.


M>Я утверждаю, что для такого кода:

M>1) по объему работы это не проще перевода на await/async
На порядок проще.
Вот у тебя код:
var details1 = someBigDao.complexBusinessLogicWhichDoesALotOfSQLQueriesSynchronously();//работает 20 секунд
var details2 = someService.itGoesToNetworkAndDownloadsDataUsingSomeCrazySoapFramework();//работает 30 секунд
return compbine(details1, details2);//общее время 50 секунд

В шарпе если ты такой код завернёшь в async, то толку никакого, т.к. первый же sql.execute() полезет синхронно в сокет и заблокирует твой async пока тот ждёт ответа от sql-сервера. Чтобы эти два метода запустить и чтобы они работали одновременно — тебе нужно запустить два честных треда.
Либо переписать всё на async-методы, чтобы они протаскивали Task по всему коду:
Т.е. если где-то внутре есть код типа
Result complexBusinessLogicWhichDoesALotOfSQLQueriesSynchronously()
{
  var r1 = sql.query(aaa);
  var r2 = sql.query(bbb);
  var r3 = sql.query(ccc);
  var r4 = anotherStuffWhichDoesSql(r2);
  return new Result(....);
}

то каждый sql.query тебе нужно придётся оборачивать в async и так по всей глубине стека.

С виртуальными тредами — ты просто пускаешь эти два метода и они работают параллельно:

var details1 = executor.submit(() -> someDao.complexBusinessLogicWhichDoesALotOfSQLQueriesSynchronously());
var details2 = executor.submit(() -> someService.downloadDataUsingSomeCrazySoapFramework()));
return combine(details1.join(), details2.join());//общее время 30 секунд

Всё. Ничего внутри someDao или someService менять не нужно.

M>2) await/async позволил бы писать более "плоский" код (меньше вложенных блоков кода)

Не позволил бы. Или показывай что ты имеешь в виду.

M>Executors.newVirtualThreadPerTaskExecutor, которыей я упомянул в соседнем сообщении, частично облегчает ситуацию — с возвратом результата Callable и пробросом исключения (в виде ExecutionException)

Проброс исключений, callable и прочее не имеет никакого отношения к сабжу.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 10.05.2023 15:06 · . Предыдущая версия . Еще …
Отредактировано 10.05.2023 15:02 · . Предыдущая версия .
Re[7]: Киллер фича JDK 21 - virtual threads
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 10.05.23 15:04
Оценка:
Здравствуйте, ·, Вы писали:


·>Т.е. у тебя есть какой-то обычный бизнес-код с синхронным readAllBytes — и у него никакого Task/async нет. И join нужен только собственно чтобы дождаться результата от всех тредов.


Интересно а как сосуществуют виртуальные потоки с тасками?
https://learn.microsoft.com/en-us/dotnet/api/system.threading.asynclocal-1?redirectedfrom=MSDN&amp;view=net-7.0
и солнце б утром не вставало, когда бы не было меня
Re[7]: Киллер фича JDK 21 - virtual threads
От: · Великобритания  
Дата: 10.05.23 15:14
Оценка: 6 (1)
Здравствуйте, m2user, Вы писали:

M>Executors.newVirtualThreadPerTaskExecutor, которыей я упомянул в соседнем сообщении, частично облегчает ситуацию — с возвратом результата Callable и пробросом исключения (в виде ExecutionException)

Наверное ты вот это хочешь. Но это уже не новости, в JDK 19 уже доступно:
Response handle() throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
        Future<String>  user  = scope.fork(() -> findUser());
        Future<Integer> order = scope.fork(() -> fetchOrder());

        scope.join();           // Join both forks
        scope.throwIfFailed();  // ... and propagate errors

        // Here, both forks have succeeded, so compose their results
        return new Response(user.resultNow(), order.resultNow());
    }
}


Опять же, это ортогонально к VT, работает на любых тредах, и на реальных, и на виртуальных.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: Киллер фича JDK 21 - virtual threads
От: · Великобритания  
Дата: 10.05.23 15:23
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>·>Т.е. у тебя есть какой-то обычный бизнес-код с синхронным readAllBytes — и у него никакого Task/async нет. И join нужен только собственно чтобы дождаться результата от всех тредов.

S>Интересно а как сосуществуют виртуальные потоки с тасками?
Я вопрос не понял. Тасков нет никаких с виртуальными потоками.
Отдельный AsyncLocal никакой не нужен, т.к. работает ровно тот же ThreadLocal.

Помимо морально устаревшенго ThreadLocal пилят ещё ScopedValue
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 10.05.2023 15:28 · . Предыдущая версия .
Re[9]: Киллер фича JDK 21 - virtual threads
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 10.05.23 15:30
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, Serginio1, Вы писали:


S>>·>Т.е. у тебя есть какой-то обычный бизнес-код с синхронным readAllBytes — и у него никакого Task/async нет. И join нужен только собственно чтобы дождаться результата от всех тредов.


S>>Интересно а как сосуществуют виртуальные потоки с тасками?

·>Я вопрос не понял. Тасков нет никаких с виртуальными потоками.
Ну например в .Net уже и не найти синхронных методов.
Я так понимаю, что перед вызовом readAllBytes сохраняется стек, вызывается асинхронный метод по завершении которого возвращается стек и продолжение происходит с после readAllBytes.

То есть компилятор должен знать что есть асинхронный readAllBytes?

Можно ли смешивать асинхронный код и виртуальные потоки?
и солнце б утром не вставало, когда бы не было меня
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.