를 사용하는 경우, 두 번째 의존 Future
다시 호출 Future(<not completed>)
Future.onComplete
되면 항상. 2 개의 Future
을 사용하는 다른 구성에서는이 동작이 발생하지 않습니다.미래 (<완료되지 않은>) Future.map 연결자 첫 번째 <code>Future</code>을 처리하는 <code>Future.map</code>을 사용한 후
미래가 분명히 완료되지 않은 이유는 누구나 Future.onComplete
이 호출되는 이유를 설명 할 수 있습니까?
스칼라 2.12.3이 사용됩니다. 필요한 경우이 문제를 평가하려면 다음을 잘라내어 붙여 넣으십시오.
import scala.collection.mutable.ListBuffer
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.{Failure, Success}
object FutureNotCompleted {
def threadNumber: String = f"${Thread.currentThread().getId.toInt}%2d"
/////////////////////////////////////////////////////
// Future completion control
/////////////////////////////////////////////////////
var futures: ListBuffer[Future[Any]] = ListBuffer()
def add(future: Future[Any]): Unit = synchronized(futures += future)
def remove(future: Future[Any]): Unit = synchronized(futures = futures.filter(_ != future))
def loopTillCompleted: Unit = {
var futuresOnList = true;
while (futuresOnList) {
Thread.sleep(100)
for (future <- futures) {
if (future.isCompleted) {
future.value.get match {
case Success(v) => println(s"${threadNumber} Success: ${v}")
case Failure(e) => println(s"${threadNumber} Error: ${e}")
}
remove(future)
}
}
if (futures.size == 0) futuresOnList = false
}
}
/////////////////////////////////////////////////////
// Future factory
/////////////////////////////////////////////////////
def createRegisteredFuture: Future[Int] = {
val future = createFuture
add(future)
future
}
def createFuture: Future[Int] = Future {
val i = (Math.random() * 1000).toInt
println(s"${threadNumber} Future work start: ${i}")
Thread.sleep((Math.random() * 1000).toLong)
println(s"${threadNumber} Future work stop: ${i}")
if (Math.random > 0.7) throw new RuntimeException(s"${threadNumber} Error for ${i}")
i
}
/////////////////////////////////////////////////////
// Functions exhibiting Future use conditions
/////////////////////////////////////////////////////
def futureDoesNotComplete: Unit = {
val f1 = createRegisteredFuture
val f2 = f1.map {
i => createRegisteredFuture
}
// This is never completed at the time the 'onComplete' callback is called
f2.onComplete({
case Success(j) => println(s"${threadNumber} j: ${j} ")
case Failure(e) => println(s"${threadNumber} f2 Failure: ${e}")
})
loopTillCompleted
println(s"${threadNumber} All done.")
}
def futureCompletes: Unit = {
val f1 = createRegisteredFuture
f1.onComplete({
case Success(i) => {
val f2 = createRegisteredFuture
f2.onComplete({
case Success(j) => println(s"${threadNumber} i: ${i} j: ${j} ${i}+${j}=${i + j}")
case Failure(e) => println(s"${threadNumber} f2 Failure: ${e}")
})
}
case Failure(e) => println(s"${threadNumber} f1 Failure: ${e}")
})
loopTillCompleted
println(s"${threadNumber} All done.")
}
def futureCompletesFor: Unit = {
for {
f1 <- createRegisteredFuture
f2 <- createRegisteredFuture
} yield {
println(s"f1: ${f1} f2: ${f2}: f1+f2=${f1+f2}")
}
loopTillCompleted
println(s"${threadNumber} All done.")
}
def main(a: Array[String]): Unit = {
// futureCompletes
futureDoesNotComplete
// futureCompletesFor
}
}
것은 내가이 페이지의 예제를 통해 일하는 : http://docs.scala-lang.org/overviews/core/futures.html#functional-composition-and-for-comprehensions. 해당 페이지 하나의 중간에 는 발견 : '발 rateQuote = 미래 { connection.getCurrentValue (USD) } 발 구매 = rateQuote지도 {인용 => 경우 (isProfitable (따옴표)) connection.buy을 (양, 따옴표) 다른 가}' 어디'connection.buy'가있다)) ("수익성이 없다" } 구매는 onSuccess {_ =>에 println ("구매"+ 양 + "USD" 경우 새로운 예외를 던져 미래. 제공된 예를 재현 한 것처럼 보입니다. 아마 아닐거야. –
이 예제와 예제의 주된 차이점은 콜백 예제에서 한 가지 더 미래를 감안한 다음 해당 페이지의 맵 예제에서 사라진다는 점입니다. 코드에서 맵핑 할 때 Future [Int [Int]]를 얻게됩니다. 'val f2 : Future [Future [Int]] = ...'에 명시 적으로 타입을 설정하면 이것을 검증 할 수 있습니다. – ameer