2016-06-02 3 views
1

ich den folgenden Code haben:Futures ausgeführt, um, obwohl es keine Abhängigkeit ist

def f1: Future[Unit] = Future { 
    Thread sleep 10000 
    println("1") 
    1 
    } 

    def f2: Future[Unit] = Future { 
    Thread sleep 5 
    println("2") 
    } 

    def f3(x: Unit, y: Unit): Future[Unit] = Future { 
    Thread sleep 10 
    println("3") 
    } 

    def main(args: Array[String]): Unit = { 

    val f = for { 
     r1 <- f1 
     r2 <- f2 
     r3 <- f3(r1, r2) 
    } yield r3 

    Await.result(f, Duration.Inf) 
    } 

f3 hängt von f2 und f1

es keine Abhängigkeit zwischen f1 und f2

Wenn ich laufen der Code, den ich bekomme:

1 
2 
3 

Ich möchte f1 und f2 parallel laufen aber vor f3.

2 
1 
3 

Wie kann ich das tun: So weil f2 vor f1 die Ausgabe sollte beendet werden soll?

+1

Sie sie nicht parallel ausgeführt werden können und eine vor dem anderen zu beenden erwarten. –

+0

Möglicherweise relevant: https://www.reddit.com/r/scala/comments/3zofjl/why_is_future_totally_unusable/ – Reactormonk

Antwort

2
val f = f1 zip f2 flatMap f3.tupled 

Oder, wenn Sie aus irgendeinem Grund auf mit for Verständnis bestehen:

val f = for { 
    (r1, r2) <- f1 zip f2 
    r3 <- f3(r1, r2) 
} yield r3 
+0

Vielen Dank! Ich habe nur eine zweite Frage: Wenn zip den Typ '[a] -> [b] -> [(a, b)]' hat, dann sollte das Ergebnis, wenn Sie es auf zwei 'Future [Unit]' verwenden, 'Future sein [(Einheit, Einheit)] '. Sollte das nicht bedeuten, dass die Ergebnisse der beiden ursprünglichen Futures gleichzeitig zurückgegeben werden? Wenn die Erklärung zu lang ist, könntest du mich bitte zu einem Artikel darüber umleiten? – octavian

+1

Hängt davon ab, was Sie mit "werden zurückgegeben" meinen. Die resultierende Zukunft ist erfüllt, wenn beide ursprünglichen Zukünfte erfüllt sind, ja, das ist der springende Punkt. Ist es nicht? – Dima

3

Ihr für Verständnis sie zwingt, in dieser Reihenfolge auszuführen. Das Verständnis ist eigentlich syntaktischer Zucker für die Funktionen map, flatMap und withFilter. In Ihrem Fall, nur flatMap. Es wird zu diesem Ausdruck erweitert werden:

f1.flatMap(r1 => f2.flatMap(r2 => f3(r1, r2))) 

Wie man hier sehen kann, die Funktion zu f1.flatMap weitergegeben wird erst f1 Ausführung ist abgeschlossen bezeichnet werden.

Ein einfacher Weg, um dieses Problem zu lösen, wäre die Zukunft vor dem für Verständnis zu instanziiert, wie folgt aus:

val future1 = f1 
val future2 = f2 

val f = for { 
    r1 <- future1 
    r2 <- future2 
    r3 <- f3(r1, r2) 
} yield r3 
+0

Warum ist es anders für Vals? – slouc

+0

Ein Wert wird sofort ausgewertet. Ein Def wird jedes Mal ausgewertet, wenn Sie es verwenden. Ein lazy val wird bei der ersten Verwendung ausgewertet. – marstran

+0

Ich weiß das, aber ich dachte, dass das Setzen einer Zukunft als ein Wert von etwas val wird einfach (sofort) den Wert als eine Zukunft einer Operation auswerten, nicht um auch die Operation selbst sofort zu starten. Bedeutet das, dass in dem Code, den Sie gepostet haben, das Ganze für das Verständnis mit zehn oder so zweiter Verzögerung (nicht bis alle Futures berechnet sind) passiert? – slouc

Verwandte Themen