質問

I have a question about scala's Future.

Currently I have a program that runs through a directory and checks if there is a document. If there is a file the program should convert these file into a ".pdf"

My Code looks like this (It's pseudocode):

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

Is this valid code or do I need to wait for the return value?

Are there any other alternative's that are as lightweight as Futures?

役に立ちましたか?

解決

To convert inside a Future, simply use map and flatMap. The actual operations are performed asynchronously when the callbacks are complete, but they are type safe.

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.
   }
}

他のヒント

Warning! If any Future throws a "NonFatal" error, it will be swallowed. This is a serious gotcha when using Future[Unit]: if no code ever evaluates the future, errors can disappear down a black hole. (It affects any Future[_], but if you are returning a value, you normally do something with it, so the error is discovered.)

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

scala> res16: scala.concurrent.Future[Nothing] = scala.concurrent.impl.Promise$DefaultPromise@64dd3f78

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

scala> res11: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@65c8295b

An alternative which accomplishes the same thing, but does not hide the error:

scala> val context = scala.concurrent.ExecutionContext.Implicits.global
context.execute(new Runnable {
  def run() = throw new IllegalArgumentException("foo")
})
context: scala.concurrent.ExecutionContextExecutor = scala.concurrent.impl.ExecutionContextImpl@1fff4cac

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)

Yes, that is valid. All the Futures you create will be run, and their return values will be discarded and garbage collected.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top