Re[53]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.01.26 18:13
Оценка:
Здравствуйте, ·, Вы писали:

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


S>>·>Выполнение в отдельном потоке означает параллельное выполнение. Это не отвечает на вопрос _зачем_ метод обязан быть асинхронным.

S>> Задача может выполняться как в отдельном потоке LongRunning, так и пуле потоков. А там можно настроить, что бы пул потока состоял из одного потока.
S>>Кроме того операции ввода вывода используют один поток использую один поток для контроля выполнения через контроллер.
·>ЗАЧЕМ?? Ты путаешь средство и цель.

S>>·>Речь о коде на языке программирования идёт, а не об операционной системе.

S>> Мы говорим об асинхронных методах, которые используют операции ввода вывода. Ты же спрашиваешь зачем использовать асинхронный код.
·>Зачем о них говорить? Почему в коде нельзя использовать синхронные операции ввода-вывода?

Мы по кругу одно и тоже обсуждаем. Я уже тебе писал про почему лучше использовать асинхронные методы.
S>>·>_Зачем_ он отвечает за параллельность?
S>> Затем, что Task работает как с потоками так и пулом потоков со своим планировщиком. Так же компилятор создает класс энумератор со state machine с вызовом MoveNext после выполнения await
·>Это средство, а не цель. Мне, как программисту, не надо создавать энумераторы. Мне, как программисту, надо выполнить миллион операций ввода-вывода.

Ты и не создаешь. За тебя это делает компилятор.

S>>·>Или для тебя сложностью является наличие выбора?

S>>Вот именно, что апи зависит от задач. Task универсален и легко читаем.
·>Нифига он не легко читаем. Примеры асинхронных очередей и т.п. ты мне тут показывал.

Угу смотрю я на твои StructuredTaskScope и поражаюсь явистам.

S>>·>Нет, за параллельность отвечают потоки. Создаёшь много потоков — они выполяются параллельно. То что тебе _приходится_ использовать асинхронность — это недостаток платформенных тредов. Ты их не можешь запускать миллионами, поэтому _приходится_ переписывать "старый" код. Иначе всё просто падает нахрен.

S>> Task это задача. Она отвязана от потоков. Еще раз внимательно читаем про операции ввода вывода, TaskCompletionSource
S>> Что там внутри происходит зависит от планировщика, пула потоков, опций для Task.
·>Угу. Но зачем? Почему нельзя просто писать обычный код с обычными синхронными операциями?

А потому, что кроме асинхронного выполнения есть и параллельное использование задач. Или без ожидания их выполнения.

Опять же зачем в Java StructuredTaskScope

Задачи через WhenAll, WhenAny, ContinueWith, CancellationToken намного проще использовать нежели StructuredTaskScope.

CancellationToken например нужен после выполнения WhenAny, что бы остановить невыполненные задачи.
и солнце б утром не вставало, когда бы не было меня
Re[55]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.01.26 18:29
Оценка:
Здравствуйте, ·, Вы писали:

S>>·>Ты задал вопрос: "как отличать Task как асинхронное и параллельное использование?". Я попросил уточнить: "с какой целью отличать?". Так зачем их отличать?

S>>Вот у тебя есть метод

S>>
S>>File.WriteAllBytesAsync("file1");
S>>

·>Зачем мне такой метод? Что плохого с File.WriteAllBytes("file1")?

S>>Не дожидаясь результата записи

·>Не надо так делать. Если тебе не важны результаты, то нафиг вообще его вызывать?

То есть например при записи логов мне не нужно знать записался он или нет.
Результат в записи лог мне не важен. Важно выполнение кода. Если в лог не записалось, то разбираться будем потом.


S>>·>Ещё раз. Это WhenAny говно в java уже есть очень давно. Но говном быть не перестаёт, т.к. усложняет код.

S>>Угу WhenAny позволяет получить результат первого выполненого и отменить выполнение еще невыполненных.
S>>Или обработать результат первого выполненного.
S>> В чем говно непонятно.
S>>Обработка асинхронных задач по мере их выполнения (C#)
·>Код сложнее. Сам же несколько сообщений назад согласился.

Сложнее по сравнению с чем? Как ты с виртуальными потоками будешь делать WhenAny?
Мне нужна первая выполненная задача!

S>> Еще раз несложно с помощью ИИ написать создание асинхронных методов если в них есть методы с имеющие методы с суффиксом Async

·>Можно. Но зачем, если есть возможно не писать такое гно вообще?

Для тебя говно, для меня нормальный универсальный код.

S>>·>Потому что не могут. Синхронный код в c# не масштабируется.

S>> Еще раз несложно через Roslyn преобразовать код.
·>Сложно. Потребуются виртуальные потоки.

Ты не пользовался анализаторами и преобразователями кода. Сейчас с ИИ несложно набросать такой преобразователь.
Виртуальные потоки хороши, но только для старого кода.

Если мы пишем новый код с 12 года, то виртуальные потоки говно ибо не универсальны.

Кстати я могу Task создать через Task.Run или TaskCompletionSource. Как для виртуальных потоков создавать такие асинхронные методы

Виртуальные потоки Java 21 — чувак, где мой lock?
и солнце б утром не вставало, когда бы не было меня
Re[54]: Можно ли избавиться от async|await?
От: SkyDance Земля  
Дата: 12.01.26 18:33
Оценка:
S> А потому, что кроме асинхронного выполнения есть и параллельное использование задач. Или без ожидания их выполнения.

Нет никакого "параллельного выполнения задач", и задач тоже нет. Если у тебя есть виртуальные потоки, ты просто пишешь синхронный код, добавляя параллельность только там, где это требуется. Все эти Task'и — не более чем протекшая абстракция, из-за отсутствия возможности отделить IO-bound от CPU-bound, и уметь вытеснять оба типа задач.
Re[54]: Можно ли избавиться от async|await?
От: · Великобритания  
Дата: 12.01.26 20:10
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>·>Зачем о них говорить? Почему в коде нельзя использовать синхронные операции ввода-вывода?

S> Мы по кругу одно и тоже обсуждаем. Я уже тебе писал про почему лучше использовать асинхронные методы.
Потому что у тебя порочный круг.

S>>> Затем, что Task работает как с потоками так и пулом потоков со своим планировщиком. Так же компилятор создает класс энумератор со state machine с вызовом MoveNext после выполнения await

S>·>Это средство, а не цель. Мне, как программисту, не надо создавать энумераторы. Мне, как программисту, надо выполнить миллион операций ввода-вывода.
S> Ты и не создаешь. За тебя это делает компилятор.
Мне приходится расставлять async/await. Компилятор это делать не умеет.

S>>>Вот именно, что апи зависит от задач. Task универсален и легко читаем.

S>·>Нифига он не легко читаем. Примеры асинхронных очередей и т.п. ты мне тут показывал.
S> Угу смотрю я на твои StructuredTaskScope и поражаюсь явистам.
Так с WhenAny код будет ещё сложнее.

S>>> Task это задача. Она отвязана от потоков. Еще раз внимательно читаем про операции ввода вывода, TaskCompletionSource

S>>> Что там внутри происходит зависит от планировщика, пула потоков, опций для Task.
S>·>Угу. Но зачем? Почему нельзя просто писать обычный код с обычными синхронными операциями?
S> А потому, что кроме асинхронного выполнения есть и параллельное использование задач. Или без ожидания их выполнения.
Так зачем это асинхронное выполнение нужно? Для параллельного вычисления есть треды.

S>Опять же зачем в Java StructuredTaskScope

Чтобы завернуть типичные шаблоны параллелизации в минимальный простой код.

S>Задачи через WhenAll, WhenAny, ContinueWith, CancellationToken намного проще использовать нежели StructuredTaskScope.

Это ложь.

S>CancellationToken например нужен после выполнения WhenAny, что бы остановить невыполненные задачи.

С тредами CancellationToken не нужен вообще. А StructuredTaskScope сам заботится об остановке задач.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[56]: Можно ли избавиться от async|await?
От: · Великобритания  
Дата: 12.01.26 20:26
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>>>Не дожидаясь результата записи

S>·>Не надо так делать. Если тебе не важны результаты, то нафиг вообще его вызывать?
S> То есть например при записи логов мне не нужно знать записался он или нет.
S>Результат в записи лог мне не важен. Важно выполнение кода. Если в лог не записалось, то разбираться будем потом.
По идее это должна решать система логгирования. Если мы хотим не терять сообщения, то надо блокировать. Т.е. в самом коде должно быть
logger.info("message");

А потом уже можно настроить по ходу — блокируемся ли, или начинаем дропать сообщения, или при переполнении очереди — начать слать куда-нибудь в другое место. Притом в зависимости от logger level.

Но если тебе хочется запустить параллельно кусок кода, то ты просто запускаешь и... собственно всё:
Thread.ofVirtual().start(() -> File.WriteAllBytes("file1"));

И не нужно дублировать каждый метод. Загляни в доку File — и посмотри, что там методов в два раза больше, чем могло бы быть!

S>>>Обработка асинхронных задач по мере их выполнения (C#)

S>·>Код сложнее. Сам же несколько сообщений назад согласился.
S> Сложнее по сравнению с чем? Как ты с виртуальными потоками будешь делать WhenAny?
S>Мне нужна первая выполненная задача!
Я уже показывал код с anySuccessfulOrThrow — ровно три строчки. Заметь, код, который ответственнен за параллелизацию находится строго внутри StructuredTaskScope. Весь другой код, и выше и ниже — обычный синхронный. Не надо по всему стеку протаскивать async/await и CancellableToken.

S>>>·>Потому что не могут. Синхронный код в c# не масштабируется.

S>>> Еще раз несложно через Roslyn преобразовать код.
S>·>Сложно. Потребуются виртуальные потоки.
S> Ты не пользовался анализаторами и преобразователями кода. Сейчас с ИИ несложно набросать такой преобразователь.
S>Виртуальные потоки хороши, но только для старого кода.


S>Если мы пишем новый код с 12 года, то виртуальные потоки говно ибо не универсальны.

S>Кстати я могу Task создать через Task.Run или TaskCompletionSource. Как для виртуальных потоков создавать такие асинхронные методы
Никак. Зачем их создавать? Просто запускаешь поток, и всё.

S>Виртуальные потоки Java 21 — чувак, где мой lock?

Ты об этом уже писал, и я тебе уже про это отвечал. Хинт: Java 25.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[55]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.01.26 07:55
Оценка:
Здравствуйте, ·, Вы писали:


S>>CancellationToken например нужен после выполнения WhenAny, что бы остановить невыполненные задачи.

·>С тредами CancellationToken не нужен вообще. А StructuredTaskScope сам заботится об остановке задач.

То есть в StructuredTaskScope есть аналог WhenAny?

А если мне нужно после выполнения WhenAny вызвать еще раз WhenAny без завершенной задачи?
и солнце б утром не вставало, когда бы не было меня
Re[57]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.01.26 08:01
Оценка:
Здравствуйте, ·, Вы писали:


S>>>>Не дожидаясь результата записи

S>>·>Не надо так делать. Если тебе не важны результаты, то нафиг вообще его вызывать?
S>> То есть например при записи логов мне не нужно знать записался он или нет.
S>>Результат в записи лог мне не важен. Важно выполнение кода. Если в лог не записалось, то разбираться будем потом.
·>По идее это должна решать система логгирования. Если мы хотим не терять сообщения, то надо блокировать. Т.е. в самом коде должно быть
·>
·>logger.info("message");
·>

·>А потом уже можно настроить по ходу — блокируемся ли, или начинаем дропать сообщения, или при переполнении очереди — начать слать куда-нибудь в другое место. Притом в зависимости от logger level.

Ну и вышла у тебя ошибка логирования. Останавливаем работу программы?
Или хрен с ним с логированием, но программ работает и самолет летит.

·>Но если тебе хочется запустить параллельно кусок кода, то ты просто запускаешь и... собственно всё:

·>
·>Thread.ofVirtual().start(() -> File.WriteAllBytes("file1"));
·>

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

Во запускаешь отдельный поток. И это упрощение?

S>>>>Обработка асинхронных задач по мере их выполнения (C#)

S>>·>Код сложнее. Сам же несколько сообщений назад согласился.
S>> Сложнее по сравнению с чем? Как ты с виртуальными потоками будешь делать WhenAny?
S>>Мне нужна первая выполненная задача!
·>Я уже показывал код с anySuccessfulOrThrow — ровно три строчки. Заметь, код, который ответственнен за параллелизацию находится строго внутри StructuredTaskScope. Весь другой код, и выше и ниже — обычный синхронный. Не надо по всему стеку протаскивать async/await и CancellableToken.

Еще раз мне нужно по WhenAny остановить все оставшиеся задачи либо для оставшихся задач вызвать WhenAny.
В твоем anySuccessfulResultOrThrow только первый вариант. Кстати привел бы код anySuccessfulResultOrThrow и потом уже говорил, что сложнее.
Ты так и не привел пример Обработка асинхронных задач по мере их выполнения (C#)

Там есть Task.WhenEach.

await foreach (Task<int> t in Task.WhenEach(downloadTasks))
    {
        total += await t;
    }

Что касается StructuredTaskScope то такой метод и на C# несложно. Проблем нет.

S>>>>·>Потому что не могут. Синхронный код в c# не масштабируется.

S>>>> Еще раз несложно через Roslyn преобразовать код.
S>>·>Сложно. Потребуются виртуальные потоки.
S>> Ты не пользовался анализаторами и преобразователями кода. Сейчас с ИИ несложно набросать такой преобразователь.
S>>Виртуальные потоки хороши, но только для старого кода.
·>

S>>Если мы пишем новый код с 12 года, то виртуальные потоки говно ибо не универсальны.

S>>Кстати я могу Task создать через Task.Run или TaskCompletionSource. Как для виртуальных потоков создавать такие асинхронные методы
·>Никак. Зачем их создавать? Просто запускаешь поток, и всё.

S>>Виртуальные потоки Java 21 — чувак, где мой lock?

·> Ты об этом уже писал, и я тебе уже про это отвечал. Хинт: Java 25.

Угу. А ещё выйдет 26. А таски работают с 12 года, а вы нормальную асинхронную систему сделать до сих пор не можете и хвалитесь при этом.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 13.01.2026 8:30 Serginio1 . Предыдущая версия . Еще …
Отредактировано 13.01.2026 8:16 Serginio1 . Предыдущая версия .
Отредактировано 13.01.2026 8:11 Serginio1 . Предыдущая версия .
Отредактировано 13.01.2026 8:07 Serginio1 . Предыдущая версия .
Re[57]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.01.26 09:04
Оценка:
Здравствуйте, ·, Вы писали:

Ты так и не ответил

Кстати я могу Task создать через Task.Run или TaskCompletionSource. Как для виртуальных потоков создавать такие асинхронные методы?

Читаю

https://growth-community.tilda.ws/digest_nov_29/java

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

Помните, что в Java 15 и более поздних версиях ввод/вывод выполняется неблокирующим образом, согласно JEP 353 и JEP 373. Поэтому носитель теперь может свободно монтировать другой виртуальный поток и продолжать выполнение, пока блокирующий ввод/вывод из первого виртуального потока выполняется в фоновом режиме.

Планировщик на уровне ВМ не будет перепланировать заблокированный виртуальный поток до тех пор, пока операция ввода-вывода не будет завершена и не появятся данные для получения.

На сегодняшний день большинство распространенных операций блокировки были адаптированы для поддержки виртуальных потоков. Однако некоторые операции, такие как Object.wait(), пока не поддерживаются и, наоборот, захватывают несущий поток . В этом случае пул потоков реагирует временным увеличением числа потоков платформы в пуле, чтобы компенсировать захваченный поток.

и солнце б утром не вставало, когда бы не было меня
Re[58]: Можно ли избавиться от async|await?
От: · Великобритания  
Дата: 13.01.26 09:53
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Кстати я могу Task создать через Task.Run или TaskCompletionSource. Как для виртуальных потоков создавать такие асинхронные методы?

Раз 5 ответил.

S>Читаю

Попробуй ещё понять.

S>некоторые операции, такие как Object.wait(), пока не поддерживаются

Эта та же проблема с synchronized, которая давно пофикшена, третий раз на ту же граблю наступаешь
Мне надоело.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[59]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.01.26 10:10
Оценка:
Здравствуйте, ·, Вы писали:


S>>Кстати я могу Task создать через Task.Run или TaskCompletionSource. Как для виртуальных потоков создавать такие асинхронные методы?

·>Раз 5 ответил.

Покажи пример. Напимер асинхронной очереди
AsyncProducerConsumerCollection

S>>Читаю

·>Попробуй ещё понять.

Что бы понять, надо код привести. Ты пока только приводил код с StructuredTaskScope и дал ссылку на аналог TaskCompletionSource.


·>

S>>некоторые операции, такие как Object.wait(), пока не поддерживаются

·>Эта та же проблема с synchronized, которая давно пофикшена, третий раз на ту же граблю наступаешь
·>Мне надоело.

Ты читаешь только то, что тебе интересно.

На сегодняшний день большинство распространенных операций блокировки были адаптированы для поддержки виртуальных потоков.


Покажи как добавить свои методы, что бы они выполнялись асинхронно.
В C# можно просто добавить
await Task.Yield();


Правда он и будет возвращать Task.

Для Java должен быть метод двойник возвращающий Future?
и солнце б утром не вставало, когда бы не было меня
Отредактировано 13.01.2026 10:17 Serginio1 . Предыдущая версия .
Re[60]: Можно ли избавиться от async|await?
От: · Великобритания  
Дата: 13.01.26 10:38
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>·>Раз 5 ответил.

S> Покажи пример. Напимер асинхронной очереди
S>AsyncProducerConsumerCollection
Зачем тебе асинхронная очередь при наличии виртуальных тредов? Используй обычный BlockingQueue.
Впрочем, пишется очень похожим образом, если очень надо, используя CompletableFuture.

S>>>Читаю

S>·>Попробуй ещё понять.
S>Что бы понять, надо код привести. Ты пока только приводил код с StructuredTaskScope и дал ссылку на аналог TaskCompletionSource.
А что тебе ещё надо? Ты ещё сам приводил ссылку на какую-то статью с десятком примеров кода.

S>·>Эта та же проблема с synchronized, которая давно пофикшена, третий раз на ту же граблю наступаешь

S>·>Мне надоело.
S> Ты читаешь только то, что тебе интересно.
Что, по-твоему, я не читаю?

S>Покажи как добавить свои методы, что бы они выполнялись асинхронно.

Куда добавить? Зачем асинхронно?

S> В C# можно просто добавить

S>
S>await Task.Yield();
S>

S>Правда он и будет возвращать Task.
S> Для Java должен быть метод двойник возвращающий Future?
Зачем? Просто Thread.yield()
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[61]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.01.26 10:54
Оценка:
Здравствуйте, ·, Вы писали:


S>>·>Раз 5 ответил.

S>> Покажи пример. Напимер асинхронной очереди
S>>AsyncProducerConsumerCollection
·>Зачем тебе асинхронная очередь при наличии виртуальных тредов? Используй обычный BlockingQueue.
·>Впрочем, пишется очень похожим образом, если очень надо, используя CompletableFuture.

Я не пишу на Java мне интересно как для TaskCompletionSource прикурутить виртуальные потоки.



static ProductPayload fetchProduct(long id) throws Exception {
    ThreadFactory named = Thread.ofVirtual().name("prod-%d", 1).factory();

    try (var scope = StructuredTaskScope.open(
        StructuredTaskScope.Joiner.<Object>allSuccessfulOrThrow(),
        cfg -> cfg.withTimeout(Duration.ofSeconds(1))
            .withThreadFactory(named))) {

      StructuredTaskScope.Subtask<Product> core = scope.fork(() -> coreApi(id));
      StructuredTaskScope.Subtask<Stock> stock = scope.fork(() -> stockApi(id));
      StructuredTaskScope.Subtask<Price> price = scope.fork(() -> priceApi(id));

      scope.join(); // throws on first failure / timeout
      return new ProductPayload(core.get(), stock.get(), price.get());
    }
  }

  void main() throws Exception {
    ProductPayload productPayload = fetchProduct(1L);
    System.out.println(productPayload);
  }


С аналогом Run.Task разобрался. Но чем это лучше Task в упор не вижу.

S>>>>Читаю

S>>·>Попробуй ещё понять.
S>>Что бы понять, надо код привести. Ты пока только приводил код с StructuredTaskScope и дал ссылку на аналог TaskCompletionSource.
·>А что тебе ещё надо? Ты ещё сам приводил ссылку на какую-то статью с десятком примеров кода.

Там аналога TaskCompletionSource нет. И сам же говоришь, что StructuredTaskScope еще превью.

S>>·>Эта та же проблема с synchronized, которая давно пофикшена, третий раз на ту же граблю наступаешь

S>>·>Мне надоело.
S>> Ты читаешь только то, что тебе интересно.
·>Что, по-твоему, я не читаю?

S>>Покажи как добавить свои методы, что бы они выполнялись асинхронно.

·>Куда добавить? Зачем асинхронно?

S>> В C# можно просто добавить

S>>
S>>await Task.Yield();
S>>

S>>Правда он и будет возвращать Task.
S>> Для Java должен быть метод двойник возвращающий Future?
·>Зачем? Просто Thread.yield()

Ну с этим согласен. Хорошо сделали. Но вот StructuredTaskScope с джойнерами не ахти то и читаемо.
То есть не вижу особенных выгод по сравнению с Task.
По Task я вижу, что метод асинхронный и могу использовать либо параллельно, либо последовательно через await.


С виртуальными потоками все в одну кучу.
Ну я рад за вас, что вам радостно.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 13.01.2026 11:06 Serginio1 . Предыдущая версия .
Re[62]: Можно ли избавиться от async|await?
От: · Великобритания  
Дата: 13.01.26 11:58
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>·>Зачем тебе асинхронная очередь при наличии виртуальных тредов? Используй обычный BlockingQueue.

S>·>Впрочем, пишется очень похожим образом, если очень надо, используя CompletableFuture.
S> Я не пишу на Java мне интересно как для TaskCompletionSource прикурутить виртуальные потоки.
Ещё раз. Это ортогональные понятия. Для виртуальных потоков task не нужен. Точнее можно создать обычный thread pool и создавать в нём таски, как обычно. Просто этому пулу передаётся фабрика виртуальных потоков, вместо платформенных по дефолту. Но это не является необходимостью, т.к. task-и не нужны для виртуальных потоков, можно использовать обычные примитивы синхронизации и любой блокирующий IO, т.к. наличие миллионов ждущих потоков не будет проблемой.
Более того, потоки — часть рантайма, а не часть ЯП. Т.е. можно не только писать свои удобные библиотеки всякой хитровывернутой многопоточки по своему вкусу, но это всё так же доступно в любом jvm-based языке — scala/kotlin какой-нибудь.

S>static ProductPayload fetchProduct(long id) throws Exception {
S>  void main() throws Exception {


S>С аналогом Run.Task разобрался. Но чем это лучше Task в упор не вижу.

Тем, что вся логика параллелизации сосредоточена внутри блока StructuredTaskScope. Вся остальная логика как вглубь coreApi/stockApi/priceApi, так и наружу fetchProduct/main — простой последовательный код. Например:
Product coreApi(long id) {
  var d1 = readFromFile(id);
  var d2 = queryDb(id, d1);
  lock();
  var d3 = downloadFromRestApi(id, d2, d1);
  unlock();
  return new Product(d3, d1);
}


Т.е. обычный синхронный код, который ничего про потоки не знает, притом может в любом месте делать любой IO, блокировки, sleep, любые всякие локи, хитрые конкурентные коллекции, и т.п. В случае шарпа все эти методы нужно будет декларировать как async и повсюду расставлять await, изобретать асинхронные очереди. САБЖ прочитай!!!

S>·>А что тебе ещё надо? Ты ещё сам приводил ссылку на какую-то статью с десятком примеров кода.

S> Там аналога TaskCompletionSource нет. И сам же говоришь, что StructuredTaskScope еще превью.
На сегодняшний момент можно использовать "Executors.newVirtualThreadPerTaskExecutor" и сабмитить таски. Недостаток — приходится говнокодить всякий WhenAll/WhenAny/cancels/results как в шарпе.

S>>>Правда он и будет возвращать Task.

S>>> Для Java должен быть метод двойник возвращающий Future?
S>·>Зачем? Просто Thread.yield()
S>Ну с этим согласен. Хорошо сделали. Но вот StructuredTaskScope с джойнерами не ахти то и читаемо.
Это просто подход обернуть стандартные паттерны параллелизма и потом легко переиспользовать.

S>То есть не вижу особенных выгод по сравнению с Task.

Сабж же.

S>По Task я вижу, что метод асинхронный и могу использовать либо параллельно, либо последовательно через await.

А с виртуальными тредами ты видишь любой метод и можешь использоваьт либо параллельно, либо последовательно без всякого await-шлака.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 13.01.2026 12:31 · . Предыдущая версия . Еще …
Отредактировано 13.01.2026 12:21 · . Предыдущая версия .
Отредактировано 13.01.2026 12:19 · . Предыдущая версия .
Отредактировано 13.01.2026 12:02 · . Предыдущая версия .
Отредактировано 13.01.2026 12:01 · . Предыдущая версия .
Отредактировано 13.01.2026 11:59 · . Предыдущая версия .
Re[63]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.01.26 12:35
Оценка:
Здравствуйте, ·, Вы писали:


S>>По Task я вижу, что метод асинхронный и могу использовать либо параллельно, либо последовательно через await.

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

Ты не понял. Есть IO методы или методы получающие результат по событию (та же асинхронная очередь). Они не напрягают CPU поэтому видя такой метод я предпочту параллельное выполнение.

await ничем не хуже
Опять же
private static readonly AsyncLock _lock = new AsyncLock();
Task<Product> coreApi(long id) {
  var d1 = readFromFile(id); // возвращает Task не дожидаемся результата
  var d2 = queryDb(id, d1);  // возвращает Task не дожидаемся результата
  using (await _lock.LockAsync())
 {
  var d3 = await downloadFromRestApi(id, d2, d1); // внутри downloadFromRestApi дожидаемся выполнения d2 и d1
  return new Product(d3, await d1);
}
}


И вот сравни такой подход c StructuredTaskScope

На самом деле Task были придуманы еще в 12 году. В Яве виртуальные потоки появились значительно позже, а StructuredTaskScope так вообще еще превью.
Виртуальные потоки однозначно хороши для синхронного кода. Но что касается асинхронного, то тут нет однозначности.
Я предпочитаю Task. Task async await показывают как я использую метод как задачу или результат задачи.
И предпочту рефакторинг кода.

Засим откланиваюсь.
и солнце б утром не вставало, когда бы не было меня
Re[64]: Можно ли избавиться от async|await?
От: · Великобритания  
Дата: 13.01.26 13:30
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>>>По Task я вижу, что метод асинхронный и могу использовать либо параллельно, либо последовательно через await.

S>·>А с виртуальными тредами ты видишь любой метод и можешь использовать либо параллельно, либо последовательно без всякого await-шлака.
S>Ты не понял. Есть IO методы или методы получающие результат по событию (та же асинхронная очередь). Они не напрягают CPU поэтому видя такой метод я предпочту параллельное выполнение.
Ты не понял. Виртуальные треды получают результат синхронно (та же синхронная очередь), блокируясь на IO в любом месте и не напрягают CPU, выполняясь параллельно.

S> await ничем не хуже

Он хуже в случае последовательного выполнения, т.к. приходится ставить везде await/async. САБЖ! И ты ещё CancellationToken забыл.

S>И вот сравни такой подход c StructuredTaskScope

Внутри coreApi никакого StructuredTaskScope, ничего не будет ВООБЩЕ. Простой линейный код. Сравни:

Product coreApi(long id) {
  var d1 = readFromFile(id);
  var d2 = queryDb(id, d1 + 42);
  synchronized(lock) {
    var d3 = downloadFromRestApi(id, d2, d1);
    return new Product(d3, d1);
  }
}

async Product coreApi(long id,  CancellationToken token = default) {
  var d1 = await readFromFile(id, token);
  var d2 = await queryDb(id, d1 + 42, token);  // используем резульат d1.
  using (await _lock.LockAsync(token))
  {
    var d3 = await downloadFromRestApi(id, d2, d1, token);
    return new Product(d3, await d1);
  }
}

И вот этот async/await надо ставить везде на всю глубину вызовов, пока не дойдём до каких-нибудь низкоуровненвых IO API. САБЖ!!!!

ИЧСХ, вот такой простой линейный код составляет 99% типичного приложения. Параллелизация обычно где-то на уровне фреймворка (ну там входящие HTTP-запросы какие-нибудь).

S>На самом деле Task были придуманы еще в 12 году. В Яве виртуальные потоки появились значительно позже, а StructuredTaskScope так вообще еще превью.

ДЕСЯТЫЙ РАЗ ПОВТОРЯЮ! Task — это аналог CompletableFuture. И появилось оно в 13 году что-ли. Заметь в моём коде вообще нигде Task/CompletableFuture нет. Они просто не нужны.

S>Виртуальные потоки однозначно хороши для синхронного кода. Но что касается асинхронного, то тут нет однозначности.

Они делают асинхронный код ненужным.

S>Я предпочитаю Task. Task async await показывают как я использую метод как задачу или результат задачи.

Сабж прочитай.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 13.01.2026 13:50 · . Предыдущая версия . Еще …
Отредактировано 13.01.2026 13:31 · . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.