В одном из предыдущих постов я разбирал как работает корутиновский пул потоков CoroutineScheduler, так вот после того как корутина выполнилась, поток должен дождаться следующей задачи, самый простой способ сделать это - проверять новые задачи в бесконечном цикле:
while(true) {
if (taskQueue.isEmpty()) {
continue
}
val task = taskQueue.poll()
task.run()
}Новые задачи добавляются в очередь и если она непустая выполняются, проблема такого подхода в том что процессор будет выполнять тысячи или даже сотни тысяч бесполезных проверок каждую секунду.
Чтобы поток не занимался бесполезной работой, а просто дожидался следующих задач была придумана удобная обертка над Unsafe API - LockSupport класс:
while (true) {
if (taskQueue.isEmpty()) {
LockSupport.park()
}
val task = taskQueue.poll()
task.run()
}
fun addTask(task: Task) {
taskQueue.push(task)
LockSupport.unpark(this)
}Суть идеи в том что метод
LockSupport.park() переводит текущий поток в состояние бездействия, а метод LockSupport.unpark() наоборот возвращает его из этого состояния, поэтому при отсутствии задач процессор не будет занят лишними инструкциями, если хотите конкретно разобраться во всей этой теме рекомендую глянуть исходники класса CoroutineScheduler,P.S. Есть еще полезный метод
LockSupport.parkNanos() если хотите задать время жизни потока при отсутствии задач, кстати в CoroutineScheduler есть такая логика - гляньте поле idleWorkerKeepAliveNs.Всем хорошего кода!