Как запустить ленивую инициализацию в рабочем потоке

У меня есть поле val mThing, которое я инициализирую by lazyThing(). Теперь я ожидаю, что вызов lazyThing() займет некоторое время, поэтому я хотел бы начать инициализацию в рабочем потоке. Очевидно, что это нормально, если появляется какой-то другой поток, который нуждается в mThing и ждет его, но я хотел бы начать инициализацию как можно скорее в рабочем потоке. Какой хороший способ сделать это в Котлине?

Или, если есть лучший шаблон, чем ленивая инициализация, я открыт для предложений.

Зачем нужен рабочий поток? Если вам все равно, блокируется ли поток во время инициализации, то, я думаю, пока инициализация является синхронной, вы можете просто запустить lazyThing() и позволить потоку заблокироваться. Я не знаю варианта использования, но обычно это довольно опасно, например, в приложениях для Android, где вы можете случайно заблокировать поток пользовательского интерфейса, который не может быть заблокирован. В других сценариях это может быть совершенно нормально.

Fred 10.03.2019 05:51

Рабочий поток @Fred необходим именно по этой причине. теоретически где-то в будущем, если что-то, зависящее от пользовательского интерфейса, нуждается в этом объекте, тогда, конечно, нам придется подождать (мы не будем блокировать поток пользовательского интерфейса, но тем временем нам может понадобиться показать счетчик), так что было бы неплохо раскрутиться. инициализация в рабочем потоке. мы можем сделать это разными способами, но я хотел бы увидеть некоторые чистые

HaydenKai 10.03.2019 08:08

Тогда я бы сказал, что ленивая инициализация с делегатами kotlin не подходит. Они будут блокировать поток, пока результат не будет доступен. Семантика также призывает к такому поведению, поскольку, как только вы читаете переменную, вы ожидаете, что результат будет прочитан синхронно. Тот факт, что он лениво инициализируется, я полагаю, это внутренняя деталь. Было бы странно читать переменную и не блокировать ее, пока она не будет готова к использованию. Какое промежуточное значение вы бы вернули? В этой ситуации я бы выставил работника или что-то, что, как знает вызывающий, будет работать асинхронно, как обычно делают наблюдаемые rxjava.

Fred 10.03.2019 08:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
186
1

Ответы 1

Вы можете указать режим синхронизации в функции lazy: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-lazy-thread-safety-mode/index.html

Простейшим способом облака является позволить JVM выполнить инициализацию при загрузке класса. Таким образом, вы можете объявить класс или объект, у которого есть поле с результатами вычислений. Далее JVM сделает необходимые блокировки:

object ComputeValueOnClassLoad {
  val value = lazyThing()
}

Первый рабочий поток будет использовать класс, он инициализирует загрузку класса и, таким образом, вычислит значение. Другие потоки будут ждать его

Другие вопросы по теме