Хорошо, поэтому сопрограммы чаще сравниваются с потоками, чем с задачами, которые вы выполняете в данном пуле потоков.Executor немного отличается тем, что у вас есть что-то, что управляет потоками и ставит в очередь задачи, которые должны быть выполнены в этих потоках.
Я также признаюсь, что я использовал куротины и актеры Котлина только в течение 6 месяцев., но давайте продолжим.
Async IO
Итак, я думаю, что одно большое отличие состоит в том, что выполнение вашей задачи в сопрограмме позволит вам достичь параллелизма наодин поток для задачи ввода-вывода, если эта задача является действительно асинхронной задачей ввода-вывода, которая должным образом возвращает управление, пока задача ввода-вывода еще выполняется.Таким образом вы можете добиться очень легкого одновременного чтения / записи с сопрограммами.Вы можете запустить 10 000 сопрограмм, одновременно считывающих данные с диска в одном потоке, и это будет происходить одновременно.Вы можете прочитать больше об асинхронном вводе-выводе здесь async io wiki
Для службы Executor, с другой стороны, если у вас есть 1 поток в вашем пуле, ваши несколько задач ввода-вывода будут выполняться и блокироваться всерия на этой теме.Даже если вы использовали асинхронную библиотеку.
Структурированный параллелизм
С сопрограммами и областью сопрограмм вы получаете то, что называется структурированным параллелизмом.Это означает, что вам нужно гораздо меньше вести учет различных фоновых задач, которые вы выполняете, чтобы вы могли правильно выполнить очистку этих задач, если вы вошли в какой-либо путь ошибки.Вместе с вашим исполнителем вам нужно будет следить за своим будущим и выполнять уборку самостоятельно.Вот действительно хорошая статья, написанная одной из команд kotlin, которая полностью объясняет эту тонкость. Структурированный параллелизм
Взаимодействие с актерами
Другое, вероятно, более нишевое преимущество заключается в том, что с сопрограммами, производителями и потребителями вы можете взаимодействовать с актерами.Действующие лица инкапсулируют состояние и обеспечивают параллельный параллельный поток благодаря общению, а не традиционным синхронизированным инструментам.Используя все это, вы можете достичь очень легкого и высококонкурентного состояния с минимальными накладными расходами.Исполнители просто не предлагают возможность взаимодействовать с синхронизированным состоянием в чем-то вроде актера, например, с 10 000 потоков или даже 1000 потоков.Вы можете с радостью запустить 100 000 сопрограмм, и если задачи приостанавливаются и дают контроль в подходящих точках, вы можете добиться некоторых превосходных результатов.Вы можете прочитать больше здесь Общее изменяемое состояние
Легкий вес
И, наконец, просто чтобы продемонстрировать, насколько легок параллельный параллелизм сопрограмм, я бы бросил вызоввам нужно сделать что-то подобное на исполнителе и посмотреть, каково общее прошедшее время (это завершено за 1160 миллисекунд на моей машине):
fun main() = runBlocking {
val start = System.currentTimeMillis()
val jobs = List(10_000){
launch {
delay(1000) // delays for 1000 millis
print(".")
}
}
jobs.forEach { it.join() }
val end = System.currentTimeMillis()
println()
println(end-start)
}
Возможно, есть и другие вещи, но, как я уже сказал, явсе еще учусь.