tgoop.com/dev_easy_notes/106
Last Update:
На данный момент в индустрии есть два варианта как мы работаем с асинхронными задачами. Мы либо используем Rx, либо Coroutines. Разумеется, существуют проекты, где эти технологии не используются, но это либо мелкие либы, либо просто мелкие проекты. На большом проекте без использования библиотеки просто невозможно будет выжить, сложность будет расти экспоненциально.
Что в Rx что в Coroutines есть абстракция, которая позволяет указать на каких потоках нужно выполнять операции. У Rx эта абстракция называется Sсheduler, у Coroutines это Dispatcher. Обе эти абстракции работают практически одинаково, поэтому просто держите в голове что все, что сказано про Sсheduler применимо и к Dispatcher.
Обычно у нас несколько вариантов Sсheduler для разных типов задач. Для похода в сеть или базу данных мы используем IO
, а для расчетов используем Computation
. Возникает вопрос, а в чем разница? Почему один Sсheduler хорош для одних задач, а другой для других?
Чтобы понять в чем разница, нужно разобраться как работают Sсheduler. Sсheduler это лишь обертка над Executor. Executor сделали для решения одной интересной задачи. Поток очень тяжелая штука по памяти, примерно 1mb, если каждый раз создавать поток, когда нам нужно сделать асинхронную задачу это может привести к OutOfMemory.
В основе Executor лежит простая идея. Если подумать, то очевидно что нам не нужно каждый раз создавать новый поток на каждую задачу. Достаточно переиспользовать имеющиеся, и просто раздавать им задачи. Чем-то такая система напоминает Looper и MessageQueue. Идем дальше, действительно ли много потоков позволят быстрее выполнять программу? На самом деле нет, после некоторого количества потоков, программа наоборот будет работать медленнее.
У нас есть процессор, в котором несколько ядер. Операционная система имитирует параллельные выполнение программ путем шедулинга. Другими словами, она дает одной программе немного поработать на процессоре, затем все приостанавливает и дает поработать другой программе. Поэтому даже если у процессора одно ядро, можно запускать несколько программ, которые будут выполнятся параллельно, ну точнее сказать "как бы параллельно".
Когда речь идет о потоках работает тот же принцип, система может сделать так, чтобы два потока по очереди работали на одном процессоре, а может запустить их параллельно на разных. Система также переключается между потоками. Операция переключения довольно дорогая, потому как нужно приостановить поток, сохранить его состояние, запустить другой поток, накатить его сохраненное состояние. Это операция называется переключение контекста. Если потоков слишком много, система будет часто переключатся м/у этими потоками и программа будет продвигаться очень медленно.
Вернемся к нашим задачам. Когда мы идем в базу или сеть мы точно будем ждать пока придут данные, как вы понимаете сеть в рамках выполнения программы довольно медленная штука. Поток в этом случае блокируется и просто ждет данные с сокета, ну или с файла есть речь о базе данных. В таком случае если у нас мало потоков, и много запросов в сеть, мы тупо будем долго ждать, т.к запросы будут идти практически последовательно. Поэтому в IO
Sсheduler, а точнее сказать в Executor этого Sсheduler много потоков, из-за блокирующих задач.
Касательно задачи расчета, мы никого не ждем, ни сети ни файловой системы, нам просто нужно быстро что-то посчитать. В этому случае нужно минимизировать переключение контекста между потоками. Именно поэтому в Сomputation
Sсheduler наоборот мало потоков. Если точнее количество потоков в Сomputation
равно количеству ядер процессора. Это позволяет минимизировать переключение контекста и тем самым ускорить выполнение расчета.
Можно также вспомнить что есть MainThread
Sсheduler, который позволяет выполнять задачи на потоке UI. Все, что делает этот Sсheduler, тупо отправляет все задачи в Looper главного потока.
В этом и заключается разница между Sсheduler. Никакой магии и особых потоков. Все максимально просто, разница лишь в количестве потоков.
BY Dev Easy Notes
Share with your friend now:
tgoop.com/dev_easy_notes/106