Comments 29
Ну бред же.
Этот «главный поток» есть недоделанное детище ведро-архитекторов. Все остальные о таком чуде просто не знают (ибо вредные вещи им просто не нужны).
На самом деле поток исполнения блокируется до получения результата. А как там при этом перераспределяются потоки операционной системы — это уже второстепенно. И даже скорее вредно отделять потоки оси от порождаемых виртуальных потоков исполнения кода, ибо всем новичкам будет казаться, что они написали «всё правильно», а на самом деле они видят виртуальную картинку, которую сочинители котлина вынуждены были сочинить из-за убогости ведра, под которое всё же приходится писать (ибо широко распространённое поделие).
В общем — тупо прячем под ковёр гнилые потроха ведроида с его дичайшей асинхронностью и смертью всего на свете из-за лени архитекторов (не захотели под UI выделить отдельный поток).
"Главный поток" — это общая черта любых платформ GUI, а не только Андроида… Как минимум, он присутствует в WINAPI, XLib, WinForms (как следствие WINAPI), WPF, AWT, Qt...
Внимательно читаем о том, что такое windows, а потом смотрим на приведённый список аббревиатур и… В общем — не надо звонить, не обладая информацией. Затем читаем про систему X Window. Ну и доказываем, как же она подходит под «это общая черта любых платформ GUI».
А может, Вы сами приведете примеры на которые Вы ссылаетесь?
Процитируйте ключевое на что вы ссылаетесь.
Бегло я не увидел на википедии ничего про потоки.
сколько не видел туториалов по иксам, там так же идет цикл событий.
Их можно сделать несколько, но везде вижу рекомендации: выделить поток под обработку событий, чтоб не парится с синхронизацией своих данных.
Замечу, что кроме Windows, Android, есть еще iOS/MacOS.
Примеров GUI платформ, где не используется цикл событий в выделенном под него потоке.
Сервер иксов да, а клиент?
Вы сейчас сравниваете внутреннюю кухню сервера иксов с тем как работает клиент.
Апельсины с помидорами не очень сравниваются.
На самом деле поток исполнения блокируется до получения результата.
Он действительно свободен. иначе бы у вас интерфейс завис.
По сути тот код передает исполнение в поток из пула Dispatchers.IO.
Потом управление передается в Dispatchers.Main, этот диспатчер по сути оберка над runOnUiThread процитированным выше.
Все довольно просто.
Интерфейс виснет от кривого архитектурного решения в ведроиде — UI ждёт, пока неграмотный программист закончит выполнять неэффективно написанную процедуру.
С наилучшими пожеланиями сообществу Kotlin. (Я совершенно искренне).
launch(Dispatchers.Main) {
val image = withContext(Dispatchers.IO) { getImage() } // контекст IO
imageView.setImageBitmap(image) // контекст Main
}
Почему для I/O операций необходимо указывать свой контекст? Разве такой код в Android не будет работать/что-то заблокирует?
launch(Dispatchers.Main) {
val image = getImage() // контекст Main, но это I/O операция
imageView.setImageBitmap(image) // контекст Main
}
Если getImage() — это метод асинхронного ввода-вывода, разве он не приостановится при выполнении чтения как любая другая асинхронная функция в контексте main? Или это какой-то задел для мультиплатформы или типа того?
Так можно делать, чтобы ограничить число параллельных блокирующих IO операций.
Иначе:
- Блокирующие операции могут остановить один из общих потоков (т.е. приложение не сможет выполнить простую операцию просто потому, что все потоки ждут, или другими словами — процессор свободен, однако программа не может его использовать). Следовательно — все блокирующие вещи должны быть отдельно.
- Много IO операций с диском всё равно не смогут выполняться параллельно (дисков-то не так много), значит желательно ограничить параллелизм, чтобы:
- Соседние операции не мешали друг другу
- Не создавать много потоков, каждый из которых кушает около 2 Мб (для стандартной Java).
Следовательно, всё блокирующее IO взаимодействие лучше выделить в отдельный пул потоков — Dispatchers.IO
Аналогичная идея есть у .Net с SynchronizationContext.
Следовательно, всё блокирующее IO взаимодействие лучше выделить в отдельный пул потоков — Dispatchers.IO
В этом собственно и был вопрос: а стоит ли метод асинхронного ввода-вывода исполнять в контексте "блокирующего IO взаимодействия"?
В теории, блокирующие I/O операции вообще не должны использоваться, и вместо них необходимо использовать их неблокирующие аналоги. А для операций, которых не имеют таких аналогов (не приходит ничего на ум) — использовать Dispatcher.IO.
Хотя вот тоже спорно — стоило ли вообще делать отдельный диспетчер для ввода-вывода, если Default справляется точно так же? Только ради ограничения по количеству параллельно выполняемых операций? Но в Default по идее также должно стоять такое же ограничение по количеству параллельно выполняющихся блокирующих потоков…
В целом имеем полное копирование истории с ведроидом — такие же неполноценные доки без пояснения выбранных архитекторами концепций.
Планируете ли вы издавать похожую книгу, только о программировании под Android?
Современный подход к конкурентности в Android: корутины в Kotlin