Как извлечь возвращаемое значение из потока в kotlin

#multithreading #kotlin

#многопоточность #kotlin

Вопрос:

Предположим, у меня есть функция, в которой я отправляю http-запрос и получаю результаты. Очевидно, что у меня есть некоторое ожидание внутри него:

 fun getDocuments(): JsonObject {
        Thread {
            return@Thread functionToGetHttpResultAsJsonObject()
        }.start()
    }
  

Что мне нужно, так это извлечь возвращаемое значение функции togethttpresultasjsonobject() в возвращаемое значение getDocuments(). Но вместо этого я получаю Unit моего желаемого JSONObject. Любая помощь будет оценена

Комментарии:

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

2. потому что functionToGetHttpResultAsJsonObject() является глобальной функцией. Он был создан раньше и должен оставаться неизменным

3. Это не объясняет, почему, если вы хотите заблокировать его до завершения и передать обратно возвращаемое значение, вы запускаете его в отдельном потоке вместо того, чтобы вызывать его напрямую (синхронно).

Ответ №1:

Начнем с того, что ваш запрос немного странный. Обычно вы не запускаете поток, чтобы заблокировать основной поток, ожидающий его завершения. Тем не менее, основной смысл потоков в том, чтобы не делать этого.

Не существует простого способа передачи информации между потоками.

Если вы хотите дождаться завершения потока внутри другого потока, вам следует вызвать .join() вместо .start()

Но это ничего не вернет. Если вы хотите синхронизировать два потока. Итак, один ожидает, пока другой вычислит некоторые данные и получит эти данные, один из способов сделать это — использовать BlockingQueue

 val queue = LinkedBlockingQueue<Int>()

Thread {
    println("concurrency ftw")
    Thread.sleep(1_000)
    println("finish sleeping!")
    queue.add(1)
}.start()

println("first")
println(queue.take())
  

Обратите внимание, что я использую .start() здесь, потому что я не хочу блокировать второй поток для его обработки.

Основной поток будет заблокирован на .take , пока кто-нибудь не добавит некоторые данные. В то же время, если второй поток прибыл первым в .add , он также будет заблокирован до тех пор, пока кто-нибудь не получит эти данные.

На этом этапе я также должен упомянуть, что в Kotlin есть концепция сопрограмм. Они очень похожи по концепции на Go «каналы», и я бы посоветовал изучить и их.