У меня есть поле val mThing, которое я инициализирую by lazyThing(). Теперь я ожидаю, что вызов lazyThing() займет некоторое время, поэтому я хотел бы начать инициализацию в рабочем потоке. Очевидно, что это нормально, если появляется какой-то другой поток, который нуждается в mThing и ждет его, но я хотел бы начать инициализацию как можно скорее в рабочем потоке. Какой хороший способ сделать это в Котлине?
Или, если есть лучший шаблон, чем ленивая инициализация, я открыт для предложений.
Рабочий поток @Fred необходим именно по этой причине. теоретически где-то в будущем, если что-то, зависящее от пользовательского интерфейса, нуждается в этом объекте, тогда, конечно, нам придется подождать (мы не будем блокировать поток пользовательского интерфейса, но тем временем нам может понадобиться показать счетчик), так что было бы неплохо раскрутиться. инициализация в рабочем потоке. мы можем сделать это разными способами, но я хотел бы увидеть некоторые чистые
Тогда я бы сказал, что ленивая инициализация с делегатами kotlin не подходит. Они будут блокировать поток, пока результат не будет доступен. Семантика также призывает к такому поведению, поскольку, как только вы читаете переменную, вы ожидаете, что результат будет прочитан синхронно. Тот факт, что он лениво инициализируется, я полагаю, это внутренняя деталь. Было бы странно читать переменную и не блокировать ее, пока она не будет готова к использованию. Какое промежуточное значение вы бы вернули? В этой ситуации я бы выставил работника или что-то, что, как знает вызывающий, будет работать асинхронно, как обычно делают наблюдаемые rxjava.





Вы можете указать режим синхронизации в функции lazy:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-lazy-thread-safety-mode/index.html
Простейшим способом облака является позволить JVM выполнить инициализацию при загрузке класса. Таким образом, вы можете объявить класс или объект, у которого есть поле с результатами вычислений. Далее JVM сделает необходимые блокировки:
object ComputeValueOnClassLoad {
val value = lazyThing()
}
Первый рабочий поток будет использовать класс, он инициализирует загрузку класса и, таким образом, вычислит значение. Другие потоки будут ждать его
Зачем нужен рабочий поток? Если вам все равно, блокируется ли поток во время инициализации, то, я думаю, пока инициализация является синхронной, вы можете просто запустить
lazyThing()и позволить потоку заблокироваться. Я не знаю варианта использования, но обычно это довольно опасно, например, в приложениях для Android, где вы можете случайно заблокировать поток пользовательского интерфейса, который не может быть заблокирован. В других сценариях это может быть совершенно нормально.