Джон не объяснил реальную точку .
Java * ExecutorService
основан на потоков , в то время как await
в C # можно сказать, что он основанна волокон .
Оба допускают многозадачность, которая разделяет вычислительные ресурсы между параллельными функциями (т. е. функциями, которые выполняются «одновременно»).Первый тип многозадачности называется упреждающим , а второй кооперативным .Исторически упреждающая многозадачность считалась более продвинутой и превосходящей кооперативную.Действительно, до того, как приоритетные многозадачности стали поддерживаться потребительскими операционными системами, компьютеры действительно были засосаны.Однако упреждающая многозадачность имеет свои недостатки.Это может быть сложно для программирования, и он использует больше памяти.
Основное различие между ними состоит в том, что упреждающая многозадачность позволяет среде выполнения (обычно самой операционной системе) останавливать любую функцию в любое время и запускатьдругая функция (и запускать их одновременно на разных процессорах).Между тем, совместная многозадачность требует, чтобы запущенная функция заканчивалась или добровольно приостанавливалась.Большинство из нас знакомы с упреждающей многозадачностью в форме многопоточности, а также с видом тщательного программирования, которое сопровождает это.Меньше знакомы с кооперативной многозадачностью, которая в наши дни часто называется волокнами или сопрограммами (в этом случае она реализуется в пользовательском пространстве внутри потоков приоритетной ОС).
В любом случае, дело в том, что ExecutorService
и await
не являются непосредственно сопоставимыми, и await
, в общем, не превосходит настоящую многопоточность (за исключением того, что он имеет хороший синтаксический сахар).Причина, по которой C # включает await
(и основывается на кооперативной многозадачности), заключается в том, что основные наборы инструментов GUI на платформе не предназначены для многопоточности, и их рефакторинг для поддержки параллелизма потребует огромного количества работы.Совместная многозадачность хорошо работает для пользовательского интерфейса, потому что большинство обработчиков событий короткие и могут выполняться последовательно.await
расширяет концепцию цикла событий, позволяя длинным обработчикам событий приостанавливать себя и возобновлять работу после того, как функция рендеринга получит шанс на запуск.Все это происходит в одном потоке на одном ядре ЦП.
То, что они оба находят общий язык, заключается в том, что они являются обеими формами многозадачности, а Future.get
и await Task
являются обеими формами синхронизации.
Как и следовало ожидать, C # не без хорошей поддержки потоков и пулов потоков.Точно так же Java содержит волокна / сопрограммы / асинхронность во многих библиотеках, таких как Servlet 3.0 и javafx.concurrent.Task
.
В ответ на Jon Skeet: Continuation (как механизм реализации пользовательского интерфейсаволокна называется) нетривиально, но потоки не менее сложны в своей реализации.Джон, возможно, был отброшен, потому что алгоритмы потоков находятся в ОС, а не в компиляторе или во время выполнения .NET.