2016-12-28 2 views
0

Der folgende Code simuliert den Online-Einkauf mithilfe von print-Anweisungen. Ich verwende Future, um ein Szenario zu simulieren, in dem ich mehrere Artikel gleichzeitig in einen Einkaufskorb lege (ich füge jedes gerade Zahlelement in den Warenkorb). Ich möchte, dass der Code am Ende ausgibt, wie viele Artikel dem Warenkorb hinzugefügt wurden.So ordnen Sie OnSuccess mehrerer Future-Objekte in Scala an

  1. Ich schaffe 5 Zukunft Objekte (so erwarte ich, Ergebnis 5 sein)
  2. ich jeden in einer Liste Zukunft speichern.
  3. I for-Schleife für die Fertigstellung jeder Zukunft
  4. ich warten soll, nachdem alle Futures ausgeführt haben, nehme ich ihre Objekt Erfolg und ihre Werte zusammenstellen (fügen Sie sie). Dies ist der Teil Ich kann nicht codieren.

    import scala.concurrent._ 
    import scala.concurrent.ExecutionContext.Implicits.global 
    import scala.util.{Failure,Success} 
    
    
    object ConcurrencyExample extends App { 
    
        //simulation of backend process of adding an object in basket 
        def addToBaskset(id:Int): Future[Int] = { 
        Future { 
         println("adding item "+id+" to shopping basket") 
         Thread.sleep(10) //simulate backend process delay 
         println("Item "+ id +" added") 
         1 //simulate the no. of items in basket 
        } 
        } 
    
        //simulate shopping. Pick even numbers and add them to baskset 
        def simulateShopping(count:Int):List[Future[Int]] = { 
        def go(c:Int, l:List[Future[Int]]):List[Future[Int]] = { 
         println("looking at more items in inventory ") 
         if(c == 0) l else 
         if (c % 2 == 0) 
         { 
         Thread.sleep(10) 
         go(c-1,addToBaskset(c)::l) 
         } 
         else { 
         Thread.sleep(10) 
         go(c-1,l) 
         } 
        } 
        go(10,List()) 
        } 
    
    
        val time = System.currentTimeMillis() 
        val shoppingList: List[Future[Int]] = List() 
    
        println("start shopping...") 
        //simulate shopping of 10 items. Even values will be added to basket using Future. Return list of Future created 
        val futures:List[Future[Int]] = simulateShopping(10) 
    
        //wait for each item in list to finish. Its results will be collected in a new list called 'result' 
        val result = for (i<- futures) yield i //we will get Success(1), 5 times 
    
        println("finished shopping. result: " +result) 
    
        **//how to I get a single integer value which is sum of all Success values?** 
    //result seem to be a List of Success() (not Future), so I tried using foldLeft or map but the code doesn't compile if I use them. I keep getting error for Unit value. 
    
    
    } 
    

Ergebnis

start shopping... 
looking at more items in inventory 
looking at more items in inventory 
adding item 10 to shopping basket 
Item 10 added 
looking at more items in inventory 
adding item 8 to shopping basket 
looking at more items in inventory 
Item 8 added 
looking at more items in inventory 
looking at more items in inventory 
adding item 6 to shopping basket 
Item 6 added 
looking at more items in inventory 
adding item 4 to shopping basket 
looking at more items in inventory 
Item 4 added 
looking at more items in inventory 
looking at more items in inventory 
adding item 2 to shopping basket 
Item 2 added 
looking at more items in inventory 
finished shopping. result: List(Success(1), Success(1), Success(1), Success(1), Success(1)) 

Prozess mit Exit-Code beendet 0

Code Nach scheinen zu arbeiten, aber warum habe ich Elemente Ergebnis als Zukunft [Int], wenn das zur Behandlung von Drucken zeigt, dass sie Erfolg (1) sind?

//y seem to be Future[Int] 
//y.value is Option(Success(1)) 
//v.get is calling 'get' on Success 
val total = result.foldLeft(0)((x,y)=>y.value match { 
    case Some(v)=>x+v.get 
    case None=>x 
    }) 
    println("finished shopping. result: " +result + "total "+total) 


finished shopping. result: List(Success(1), Success(1), Success(1), Success(1), Success(1))total 5 

Antwort

1

Sie können Future.sequence verwenden List[Future[Int]]-Future[List[Int]] zu drehen und dann sum rufen alle Elemente zu sehen, wurden hinzugefügt:

val result: Int = Await.result(Future.sequence(futures).map(_.sum), 5 seconds) 

Beachten Sie, dass Await.result nur so verwendet wird, dass der Test nicht vorzeitig endet ohne dass alle Zukünfte abgeschlossen sind.

Warum muss ich Elemente des Ergebnisses als Future [Int] behandeln, wenn der Ausdruck zeigt, dass sie Erfolg (1) sind?

Da Future[T].value eine Option[Try[T]] zurückkehrt, wo Try kann entweder Success oder Failure sein. Aber es wird nur einen Wert zurückgeben, wenn die Zukunft abgeschlossen ist. Ich würde keinen Weg gehen mit .value überhaupt.

+0

Hallo, ich brauche keine Länge, sondern Summe der Rückgabewerte von Erfolg. Ich habe meine Frage mit einem Ansatz bearbeitet, der funktioniert hat, aber ich bin verwirrt, warum ich eine Liste von Future [Int] bekommen habe, wenn der Druck zeigt, dass ich eine Liste von Erfolg habe (1) –

+0

@ManuChadha Ich habe ursprünglich 'sum' geschrieben, war aber nicht sicher, wenn es das ist, was du wolltest. Ich habe die Antwort bearbeitet. –

+0

@ManuChadha Youre zum Verständnis würde eine 'Seq [Future [Int]]' ergeben, ähnlich meiner Antwort mit 'Future.sequence'. Aber wie es derzeit aussieht, warten Sie nicht wirklich auf die Fertigstellung der Futures. "Future [T] .get" zu nennen ist definitiv nicht der empfohlene Ansatz. –

1
Future.foldLeft(futures)(0)(_ + _).foreach(result => "finished shopping. result: " +result) 
Verwandte Themen