2015-01-26 5 views
13

Выполняя этот код scala, у меня нет вывода в консоли. (Я действительно не понимаю, что происходит)Использование фьючерсов и Thread.sleep

Если я удалю Console.println("Console.println OK!") => все кажется прекрасным.

Если я удалю Thread.sleep(2000) => все кажется прекрасным.

У вас есть идеи по этому вопросу? Большое спасибо!

Клеман

import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 
import scala.concurrent.{Await, Future} 
import scala.language.postfixOps 

object ScalaFuture { 

    def main(args: Array[String]) { 

    val f: Future[String] = Future { 
     Thread.sleep(2000) 
     "future value" 
    } 

    f.onSuccess { 
     case s => { 
     Console.println("Console.println OK!") 
     System.out.println("System.out.println OK!") 
     } 
    } 

    Await.ready(f, 60 seconds) 
    } 

} 
+0

Прекрасно работает для меня. Что произойдет, если вы спите в течение нескольких секунд после 'Await.ready'? –

+0

Если я сплю несколько секунд после 'Await.ready', он отлично работает => У меня есть выход. – ctamisier

+0

Затем он должен выйти, прежде чем 'onSuccess' может выстрелить. –

ответ

21

Ваш Await ждет будущего завершения, что делается через 2 секунды, но он не ждет onSuccess обработчика, который выполняет в другом потоке (по аналогии с будущим), но после Await.ready(f, 60 seconds), поэтому процесс выходит раньше, чем вы что-то печатаете. Для того, чтобы правильно обработать его - создать новое будущее для onComplete:

val f: Future[String] = Future { 
    Thread.sleep(2000) 
    "future value" 
} 

val f2 = f map { s => 
    println("OK!") 
    println("OK!")  
} 

Await.ready(f2, 60 seconds) 
println("exit") 

Результаты для Await.ready(f, ...):

exit 
OK! 
OK! 

Результаты для Await.ready(f2, ...):

OK! 
OK! 
exit 
+0

Хорошо, я понял. Поэтому, если я не ошибаюсь: это временное решение, когда мы используем функцию main(). Считаете ли вы, что ExecutionContext задействован в этом и «специальном», это может помешать этому? ». Я посмотрел на Фьючерсы, реализованные в Twitter, и кажется, что их «Планировщик» справляется с этим (мне не нужно ждать или уже завершать будущее с одним и тем же вариантом использования), но это уже другая история. Спасибо за вашу помощь ! – ctamisier

+0

Это не обходной путь. Это правильный способ сделать такие вещи (если в приложении есть только один поток с Await) - особенно для функционального стиля - поскольку у вас есть только один результат в вашем приложении - вы должны вернуть его (и, следовательно, дождаться), чтобы 'IO', если ваше приложение основано на REPL (в других случаях - пользователь должен отключить его вручную из пользовательского интерфейса, поэтому не нужно ждать). Другой вариант - использовать ExecutionContext (и базовый ThreadPool), который создает потоки с флагом 'isDaemon' false - см. Http://stackoverflow.com/questions/16612517/execution-context-without-daemon-threads-for-futures. – dk14

+0

Почему 'Await.ready (f, ...):' print out 'OK!'? В 'f' нет' println («OK!») '. Я не знаю, как примирить «f» с таким ожидаемым выходом. –

-8

Просто положить ReadLine() в коде.

Смежные вопросы