2014-02-03 3 views
2

У меня есть вопрос о scala's Future.Будущее/обещание без ожидания результата? Обратный модуль

В настоящее время у меня есть программа, которая проходит через каталог и проверяет наличие документа. Если есть файл, программа должна преобразовать эти файлы в «.pdf»

Мой код выглядит следующим образом (это псевдокод):

for(file <- directory) { 
    if(timestamp > filetimestamp) { 
    Future { 
    // do a convert job that returns UNIT 
    } 
    } 
} 

Является ли это правильный код или мне нужно ждать возвращаемое значение?

Есть ли другие альтернативы, которые столь же легки, как и фьючерсы?

ответ

9

Для преобразования внутри Future просто используйте map и flatMap. Фактические операции выполняются асинхронно, когда обратные вызовы завершены, но они безопасны по типу.

import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 

for(file <- directory) { 
if(timestamp > filetimestamp) { 
    val future = Future { 
    // do a convert job that returns UNIT 
    } map { 
    file => // whatever you want. 
    } 
} 
+0

, как я сказал, я не хочу, чтобы ждать, пока его завершения, я просто хочу, чтобы он конвертировать и для должны перейти к следующему файлу и сделать то же самое –

+0

гм, которая выглядит легко, что вы имеете в виду, осознавая, что я делаю/блокируя поведение? Что может случиться? единственное, чего я боюсь, - это потребление памяти –

+0

@ChristianSchmitt О памяти, я помню, что библиотека Scala IO по умолчанию не выделяет ресурсы. Вы получили отличную замену от jsuereth, найденного здесь: https://github.com/jsuereth/scala-arm. – flavian

0

Да, это действительно. Все созданные вами Future s будут запущены, а их возвращаемые значения будут отброшены и собранный мусор.

6

Предупреждение! Если какое-либо Будущее выбрасывает ошибку «Нефатальная», оно будет проглочено. Это серьезная проблема при использовании Future [Unit]: если код никогда не оценивает будущее, ошибки могут исчезнуть из черной дыры. (Это влияет на любое будущее [_], но если вы возвращаете значение, вы обычно делаете что-то с ним, так что обнаружена ошибка.)

scala> import scala.concurrent.ExecutionContext.Implicits.global 
scala.concurrent.Future { throw new IllegalArgumentException("foo") } 

scala> res16: scala.concurrent.Future[Nothing] = [email protected] 

scala> import scala.concurrent.ExecutionContext.Implicits.global 
scala.concurrent.Future { throw new IllegalArgumentException("foo"); 42 } 

scala> res11: scala.concurrent.Future[Int] = [email protected] 

Альтернативой, которая выполняет то же самое, но не скрывает ошибка:

scala> val context = scala.concurrent.ExecutionContext.Implicits.global 
context.execute(new Runnable { 
    def run() = throw new IllegalArgumentException("foo") 
}) 
context: scala.concurrent.ExecutionContextExecutor = [email protected] 

scala>  |  | java.lang.IllegalArgumentException: foo 
at $line48.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1.run(<console>:34) 
at $line48.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1.run(<console>:33) 
at scala.concurrent.impl.ExecutionContextImpl$$anon$3.exec(ExecutionContextImpl.scala:107) 
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) 
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) 
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) 
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) 
Смежные вопросы