2016-10-07 2 views
1
package p1 
import scala.util.Failure 
import scala.util.Success 
import scala.concurrent.Await 
import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.duration._ 

object modCheck extends App { 

    def getStudentRoolNo(name: String) = Future { 
    println("getStudentRoolNo") 
    name match { 
     case "name1" => 1 
     case "name2" => 2 
     case _  => throw new Exception("No doesnt exist") 
    } 
    } 

    def getRank(roolNo: Int) = Future { 
    println("getRank") 
    Thread.sleep(500) 
    roolNo match { 
     case 1 => "1" 
     case 2 => "2" 
     case _ => throw new Exception("No roolNo exist") 
    } 
    } 

    def getDetails(roolNo: Int) = Future { 
    println("getDetails") 
    roolNo match { 
     case 1 => "details 1" 
     case 2 => "Details 2" 
     case _ => throw new Exception("No details exist") 
    } 
    } 

    def getStudentRecord(name: String) = { 
    for { 
     rollNo <- getStudentRoolNo(name) 
     rank <- getRank(rollNo) 
     details <- getDetails(rollNo) 
    } yield (rank + details) 

    } 

    getStudentRecord("name1").onComplete { 
    case Success(ground) => println(s"got my Details $ground") 
    case Failure(ex)  => println("Exception!" + ex) 
    } 

    Thread.sleep(2000) 

} 

Я хочу, чтобы выполнить функции getrank и getDetails параллельно в коде ниже (как только getStudentRollNo возвращается). Как я могу это достичь?исполнения фьючерсов Scala параллельно с использованием для цикла

я Пробовал ниже образом, кажется, что по-прежнему выполняется в последовательно

Пожалуйста, дайте мне знать, как выполнить параллельно

ответ

1

Будущее начинается расчет при ее создании.

for (a <- x; b <- y) yield ??? является обессахаренная к x.flatMap(a => y.map(b => ???)) flatMap() и map() выполнить это аргумент после того, как в будущем будет завершена.

getDetails() может начаться до завершения getRank() путем разделения создания Future и flatMap() вызова.

for { 
    rollNo <- getStudentRoolNo(name) 
    rankFuture = getRank(rollNo) 
    detailsFuture = getDetails(rollNo) 
    rank <- rankFuture 
    details <- detailsFuture 
    } yield (rank + details) 
+0

Его рабочий таким образом, спасибо :) –

0

Как вы уже вероятно, догадались, ваш текущий код не делает звонки на getRank и getDetails параллельно, так как ее внутри для-понимания. Его синтаксический сахар для операции map. Чтобы добиться параллелизма, вам нужно создать два фьючерса за пределами понимания.

val student = getStudentRollNo(name) 
val detailsFuture = student map {s => getRank(rollNo) } 
val rankFuture = student map {s => getDetails(rollNo) } 

for { 
    rank <- rankFuture 
    details <- detailsFuture 
} yield (rank + details) 
+0

Спасибо за предложение, я проверяю больше к написанию кода внутри for-loop (Поскольку моя фактическая сложная логика в этом много, теперь принятие вышеуказанного решения может быть немного затруднительным), я изменил вопрос, почему в этом случае он также выполняется последовательно? –

+0

Тогда может быть перемещение 'rankFuture = getRank (rollNo)' и последующих строк для получения части. Это позволит уменьшить беспорядок и гарантирует, что оба фьючерса выполняются параллельно – Richeek

+0

для { rollNo <- getStudentRoolNo (имя) rankFuture = getRank (rollNo) detailsFuture = getDetails (rollNo) ранг <- rankFuture подробности <- detailsFuture } yield (rank + details) - Его работа таким образом, спасибо :) –

0

Вы можете использовать zip в вашей для понимания, чтобы запустить два Фьючерс параллельно:

def getStudentRecord(name: String) = { 
    for { 
     rollNo <- getStudentRoolNo(name) 
     rankRollNo <- getRank(rollNo) zip getDetails(rollNo) 
    } yield rankRollNo 
    } 

В приведенном выше getRank и getDetails запускаются одновременно и результатом является строка кортежа. Если вы хотите, чтобы получить одну строку, вам нужно будет отделить rankRollNo на отдельные компоненты:

yield rankRollNo._1 + rankRollNo._2 
Смежные вопросы